En una entrada anterior vimos que SQL es lenguaje que se utiliza para interactuar con bases de datos relacionales. A su vez, el lenguaje se divide en cláusulas o comandos, que nos permiten realizar distintas operaciones.
Hoy vamos a ver una de las más importantes, la cláusula SELECT, que nos permite recuperar la información de la base de datos. Para ello, seguimos donde lo dejamos en la entrada anterior. Al seguir las instrucciones anteriores, tendrás una base de datos con una tabla que tiene 8837 filas de datos.
Al dar nuestros primeros pasos ya ejecutamos una consulta de éste tipo. La sintaxis general del SELECT es la siguiente:
Para escribir un comentario en SQL podemos utilizar --
al principio de una línea
Vemos que es bastante intuitivo, básicamente es como pedirle lo que queremos a la base de datos, pero en inglés. El único carácter que puede parecer extraño es *
, que en programación (se usa en otros sitios además de en SQL) suele significar “todo”. Por tanto, ésta consulta selecciona todas las variables o columnas de la tabla. Podríamos traducirla al español como “Selecciona todo lo que hay en la tabla que se llama Clima y muéstramelo”
También podemos seleccionar columnas específicas separándolas por comas. Ésto es útil, ya que generalmente no necesitamos trabajar con todas las variables de las tablas a la vez sino únicamente con unas pocas (especialmente cuando estamos desarrollando aplicaciones). De ésta forma, si trabajamos por ejemplo desde R o python cargaremos menos información en memoria, y se acelera la lectura de los datos.
Por cierto, si te fijas, suelo escribir los comandos SQL en mayúsculas, y el resto de los elementos de forma normal. Ésto se hace así por convención, ya que nos permite distinguir mejor el código de nuestra nomenclatura para nombrar las cosas. No obstante es opcional, SQL no suele distinguir entre mayúsculas o minúsculas (con algunas excepciones).
A las expresiones SQL completas (es decir, que no dan error por que falte algún componente) se las denomina consultas, ya que le “pedimos” información a la base de datos
Otra situación muy frecuente es que queramos recuperar únicamente las filas o los casos de la base de datos que cumplan una serie de condiciones. Aquí es donde entra la cláusula WHERE. Su sintaxis general es la siguiente:
Si ejecutamos la siguiente consulta en DB Browser for SQLite filtrará las observaciones de la tabla para devolver las filas de la estación de Segovia:
Nos devuelve 181 filas, y el campo estacion en todas ellas tiene el valor “SEGOVIA”. También podemos especificar varias condiciones, para lo que podemos utilizar los siguientes operadores:
AND
: deberán cumplirse ambas condicionesOR
: deberá cumplirse al menos una condiciónNOT
: invierte una condición (así que para que se seleccione la fila no deberá cumplirse)Ésta consulta nos devuelve las filas que pertenecen a la estación de Segovia y en las que la temperatura media (tmed) ha sido superior a 20 grados. Podemos encadenar más condiciones si queremos. En éstos casos, podemos utilizar paréntesis para agrupar condiciones. Por ejemplo
Condicion1 AND (Condicion2 OR Condicion3)
: Selecciona las filas en las que se cumple la condicion 1, y al menos una de las otras dos condiciones (o ambas).Condicion1 OR (Condicion2 AND Condicion3)
: Selecciona las filas en las que se cumple la condición 1, y también aquellas en las que se cumple la 2 y la 3 al mismo tiempo.A su vez, las condiciones pueden utilizar operadores lógicos, que permiten comparar valores. Los operadores lógicos en SQL son los siguientes:
Valor == X
: valor es igual a XValor != X
: valor distinto de XValor > X
: valor mayor que XValor < X
: valor menor que XValor >= X
: valor mayor o igual que XValor <= X
: valor menor o igual que XHay algunos más pero éstos son los más importantes. Los dos primeros funcionan para todo tipo de valores (números, texto, fechas…), y los cuatro siguientes suelen ser útiles con variables numéricas y fechas, por ejemplo:
Con ésta consulta seleccionamos todos los datos cuya fecha es anterior (menor) al 15 de Enero de 2021. En éste sentido tenemos que comentar que SQLite carece de un tipo de dato específico para fechas, por lo que las almacena en formato de texto, de modo que la fecha se pasa entre comillas. Además, conviene almacenar las fechas en formato AAAA-MM-DD, tal y como está en el comando, ya que así es más fácil ordenarlas.
También podemos recuperar las filas que contengan valores en una lista mediante el operador IN
y abriendo paréntesis. Cuando las consultas empiezan a volverse algo más complejas conviene separarlas en varias líneas y cuidar la identación para que sean más fáciles de leer:
SELECT * FROM datos_aemet
WHERE
fecha == "2021-01-15"
AND
estacion IN ("SOMOSIERRA", "GETAFE", "SEGOVIA")
Por supuesto, podemos invertir el operador IN
para que nos devuelva las filas que NO contengan ninguno de los valores en ella mediante el NOT
.
SELECT * FROM datos_aemet
WHERE
fecha == "2021-01-15"
AND
estacion NOT IN ("SOMOSIERRA", "GETAFE", "SEGOVIA")
Otro de los operadores más útiles para seleccionar filas es el LIKE
. Hemos visto que podemos seleccionar filas que tienen un valor exacto con SELECT * FROM tabla WHERE columna == "Valor"
. Pero muchas veces, no nos interesa que la coincidencia sea exacta, sino que queremos que encaje con un patrón más genérico.
Justamente ésta es la utilidad del operador LIKE. Veamos cómo podemos usarlo:
valor LIKE "patron%"
: selecciona los registros que empiezan por el patrónvalor LIKE "%patron"
: selecciona los registros que terminan por el patrónvalor LIKE "%patron%"
: selecciona los registros que contienen el patrónÉsta consulta selecciona todos los registros que pertenecen a las estaciones de los aeropuertos y a la fecha específica.
El símbolo _
significa “cualquier caracter”. Así “chic_” aceptaría las filas que contengan chico o chica, ya que la "_" acepta conincidencias con cualquiera de las opciones (aunque también aceptaría otras como chicw).
Con éstos elementos podemos seleccionar patrones de texto complejos (o fechas). Por ejemplo:
Con ésta consulta seleccionamos todos los datos de la estación de Aranjuez, para las fechas de Febrero (de cualquier año, aunque en nuestro fichero únicamente hay datos de un año), y para los días 10-19 (el primer número del día debe ser un 1 pero gracias al _
el segundo puede ser cualquiera).
El operador LIKE nos permite encontrar filas que contienen un patrones de texto
Otra de las cláusulas más utilizadas de SQL es ORDER BY, que como su nombre indica nos permite ordenar los resultados de las consultas. Su sintaxis general es la siguiente:
Si la columna contiene una variable de texto, ordenará los resultados alfabéticamente, mientras que si especificamos una variable numérica lo hará utilizando sus valores. Por ejemplo, podemos obtener las estaciones con los días más fríos con la siguiente consulta:
Especificamos el nombre de la columna que queremos utilizar para ordenar nuestros resultados y luego si queremos podemos especificar que se ordene de forma ascendente (ASC) o descendente (DESC). Si no especificamos nada SQLite por defecto realiza las ordenaciones de forma ascendente.
En ésta consulta además hemos introducido una condición especial: tmed IS NOT NULL
. Significa que únicamente quiero las filas que contengan valores para la variable tmed. Si quitamos la condición los primeros valores estarán vacíos para el campo tmed.
Podemos ordenar los resultados en función de los valores de varias variables. Además, es interesante saber que podemos ordenar los datos por columnas que no tienen por que estar incluídas en los resultados.
En éste caso ordenamos los resultados mediante la variable sol, que no está entre las columnas solicitadas.
Con lo que hemos visto en éste artículo quedan cubiertas las características más utilizadas del lenguaje SQL, por lo menos en lo que se refiere a la lectura de los datos almacenados en las bases de datos relacionales. Con la cláusula SELECT podemos especificar qué columnas queremos y con el WHERE podemos filtrar las filas. De ésta manera podemos recuperar únicamente la información que necesitamos, acelerando las lecturas y ahorrando memoria al cargar nuestros datos en otros programas.
También hemos visto que podemos ordenar nuestros resultados directamente con SQL para no tener que hacerlo en la aplicación. La mayoría de lenguajes de programación no tienen muchas utilidades para trabajar con matrices de datos, pero gracias a SQL podemos manipular los datos almacenados en forma tabular sin problema.
En el futuro seguiremos viendo otras características importantes del lenguaje. Hasta entonces, espero que éste post sea útil.