4 Selección de datos
La sentencia SELECT es, con diferencia, la más compleja de SQL. Permite desde mostrar valores de constantes o funciones, a hacer consultas en una tabla o composiciones en varias tablas juntas, limitando las columnas a mostrar, renombrándolas o creándolas; limitando el número de columnas, ordenandolas, etc.
Pero la sentencia SELECT no se limita a mostrar el contenido de una tabla o parte de ella, lo que hace en realidad es crear una tabla, o más precisamente, una relación (recordemos que SQL maneja bases de datos relacionales). Es decir, el resultado de una sentencia SELECT sobre una tabla o un conjunto de tablas, es una tabla. Esa tabla resultado tendrá un número determinado de filas, y un número de columnas, cada una con su nombre.
Esta es una de las sentencias que menos diferencias tiene con el SQL estándar en SQLite, de modo que en este capítulo repasaremos un poco sus diferentes posibilidades.
Mostrar constantes y funciones
Esta es la forma más sencilla. Podemos mostrar un valor:
sqlite> SELECT sqlite_version(); 3.7.3 sqlite>
O varios, separados por comas:
sqlite> .headers on sqlite> SELECT round(122.32), "Hola", random(); round(122.32)|"Hola"|random() 122.0|Hola|-3071908159697118318 sqlite>
Nota:
Hemos usado el comando de consola .headers on
para que se muestren las
cabeceras en los listados, indicando los nombres de las columnas.
Renombrar columnas
Siempre es posible cambiar el nombre de cada columna en la tabla resultado, usando la cláusula AS. Así, por ejemplo, la última consulta puede ser modificada para que cada columna tenga un nombre más manejable:
sqlite> SELECT round(122.32) AS numero, "Hola" AS saludo, random() AS aleatorio; numero|saludo|aleatorio 122.0|Hola|8855590400098358693 sqlite>
Más adelante usaremos este mecanismo para renombrar columnas calculadas por la aplicaciones de funciones agregadas (de grupos).
Contenido de tablas
Donde se complica la sintaxis de SELECT es al mostrar el contenido de tablas y composiciones.
Limitar columnas
La principal aplicación de las sentencias SELECT es mostrar todo o parte del contenido de una tabla. Es su forma más general mostraremos todas las filas y columnas, las columnas se muestran en el orden en que fueron creadas en la sentencia CREATE TABLE. Las filas en un orden arbitrario:
sqlite> SELECT * FROM usuario; Fulano|fulano@dominio.com Mengano|mengano@dominio.com Tulano|tulano@dominio.com Sillano|sillano@dominio.com Cascasano| sqlite>
Podemos seleccionar algunas columnas, indicando sus nombres, y separadas con comas:
sqlite> SELECT rowid,nombre FROM usuario; rowid|nombre 1|Fulano 2|Mengano 3|Tulano 4|Sillano 5|Cascasano sqlite>
Podemos renombrar columnas cuando se realice la consulta.
Limitar filas
Para limitar el número de filas hay dos caminos diferentes, limitar filtrando por ciertos valores de columnas o grupos de columnas o limitar el rango de filas a mostrar.
Cláusula WHERE
La cláusula WHERE permite filtrar los resultados, dejando sólo aquellas filas que cumplan determinadas condiciones. Después de una cláusula WHERE se puede colocar cualquier expresión booleana:
sqlite> SELECT * FROM usuario WHERE 1; nombre|email Fulano|fulano@dominio.com Mengano|mengano@dominio.com Tulano|tulano@dominio.com Sillano|sillano@dominio.com Cascasano| sqlite>
Aunque suele ser más útil usar expresiones que involucren a alguna columna:
sqlite> SELECT * FROM usuario WHERE nombre LIKE "%lano"; nombre|email Fulano|fulano@dominio.com Tulano|tulano@dominio.com Sillano|sillano@dominio.com sqlite>
Este último ejemplo muestra una relación con las filas de usuarios cuyo nombre termina en "lano".
Cláusula HAVING
El uso de esta cláusula es más esquivo. Sirve para lo mismo que WHERE, pero se aplica sobre columnas creadas con funciones agregadas. Para ver su uso crearemos y poblaremos una nueva tabla:
sqlite> CREATE TABLE pedidos ( ...> fecha DATE, ...> referencia TEXT, ...> cantidad INTEGER); sqlite> INSERT INTO pedidos VALUES(date('now', '-10 days'), 123, 321); sqlite> INSERT INTO pedidos VALUES(date('now', '-10 days'), 125, 120); sqlite> INSERT INTO pedidos VALUES(date('now', '-10 days'), 132, 100); sqlite> INSERT INTO pedidos VALUES(date('now', '-5 days'), 123, 95); sqlite> INSERT INTO pedidos VALUES(date('now', '-5 days'), 132, 174); sqlite> INSERT INTO pedidos VALUES(date('now', '-5 days'), 154, 98); sqlite> INSERT INTO pedidos VALUES(date('now', '-5 days'), 178, 150); sqlite> INSERT INTO pedidos VALUES(date('now', '-2 days'), 125, 50); sqlite> INSERT INTO pedidos VALUES(date('now', '-2 days'), 126, 150); sqlite> INSERT INTO pedidos VALUES(date('now', '-2 days'), 132, 250); sqlite> INSERT INTO pedidos VALUES(date('now', '-2 days'), 178, 140); sqlite> INSERT INTO pedidos VALUES(date('now', '-2 days'), 180, 100); sqlite> SELECT * FROM pedidos; fecha|referencia|cantidad 2012-03-13|123|321 2012-03-13|125|120 2012-03-13|132|100 2012-03-18|123|95 2012-03-18|132|174 2012-03-18|154|98 2012-03-18|178|150 2012-03-21|125|50 2012-03-21|126|150 2012-03-21|132|250 2012-03-21|178|140 2012-03-21|180|100 sqlite>
Ahora haremos una cosulta en la que sumaremos las columnas 'cantidad' para cada 'referencia' distinta:
sqlite> SELECT referencia,sum(cantidad) FROM pedidos GROUP BY referencia; referencia|sum(cantidad) 123|416 125|170 126|150 132|524 154|98 178|290 180|100 sqlite>
Si queremos limitar el número de filas a las que la suma de cantidades sea menor de 160 no podremos usar la cláusula WHERE:
sqlite> SELECT referencia,sum(cantidad) FROM pedidos WHERE sum(cantidad)<160 GROUP BY referencia; Error: misuse of aggregate: sum() sqlite>
En su lugar debemos usar HAVING:
sqlite> SELECT referencia,sum(cantidad) FROM pedidos GROUP BY referencia HAVING sum(cantidad)<160; referencia|sum(cantidad) 126|150 154|98 180|100 sqlite>
O, renombrando la columna de la suma:
sqlite> SELECT referencia,sum(cantidad) AS suma FROM pedidos GROUP BY referencia HAVING suma<160; referencia|suma 126|150 154|98 180|100 sqlite>
Cláusula LIMIT
Por último, la cláusula LIMIT nos permite limitar el número de filas de la rabla de salida:
sqlite> SELECT * FROM pedidos LIMIT 4; fecha|referencia|cantidad 2012-03-13|123|321 2012-03-13|125|120 2012-03-13|132|100 2012-03-18|123|95 sqlite>
La cláusula opcional OFFSET permite indicar un desplazamiento, por ejemplo, para obtener las cuatro filas a partir de la tercera, indicaremos un límite de 4 con un desplazamiento de 2:
SELECT * FROM pedidos LIMIT 4 OFFSET 2; fecha|referencia|cantidad 2012-03-13|132|100 2012-03-18|123|95 2012-03-18|132|174 2012-03-18|154|98
Si no se especifica una cláusula ORDER BY el orden es el mismo en que se almacenan en la tabla de origen.
Ordenar las filas
Mediante la cláusula ORDER BY podemos establecer distintos criterios para ordenar las filas. A continuación de la cláusula se especifica un nombre de columna o varios, separados por comas. Para cada columna podemos elegir un orden ascendente ASC, que es el orden por defecto; o descendente DESC:
sqlite> SELECT * FROM pedidos ORDER BY fecha DESC; fecha|referencia|cantidad 2012-03-21|125|50 2012-03-21|126|150 2012-03-21|132|250 2012-03-21|178|140 2012-03-21|180|100 2012-03-18|123|95 2012-03-18|132|174 2012-03-18|154|98 2012-03-18|178|150 2012-03-13|123|321 2012-03-13|125|120 2012-03-13|132|100 sqlite> SELECT * FROM pedidos ORDER BY fecha DESC, cantidad ASC; fecha|referencia|cantidad 2012-03-21|125|50 2012-03-21|180|100 2012-03-21|178|140 2012-03-21|126|150 2012-03-21|132|250 2012-03-18|123|95 2012-03-18|154|98 2012-03-18|178|150 2012-03-18|132|174 2012-03-13|132|100 2012-03-13|125|120 2012-03-13|123|321 sqlite>
Agrupar filas
Usando la cláusula GROUP BY podemos agrupar filas por una o varias columnas, separadas con comas:
sqlite> SELECT * FROM pedidos GROUP BY referencia; fecha|referencia|cantidad 2012-03-18|123|95 2012-03-21|125|50 2012-03-21|126|150 2012-03-21|132|250 2012-03-18|154|98 2012-03-21|178|140 2012-03-21|180|100 sqlite> SELECT fecha,count(*) AS items FROM pedidos GROUP BY fecha; fecha|items 2012-03-13|3 2012-03-18|4 2012-03-21|5 sqlite>
Por supuesto, si queremos filtrar los resultados por algún criterio, hay que tener en cuenta que esta última consulta es agregada, y por lo tanto, hay que usar la cláusula HAVING.
sqlite> SELECT fecha,count(*) AS items FROM pedidos GROUP BY fecha HAVING items>3; fecha|items 2012-03-18|4 2012-03-21|5 sqlite>
Eliminar filas duplicadas
En toda relación (o tabla) en una base de datos relacional, no debe haber filas repetidas. Esto es parte de la definición de las bases de datos relacionales. La sentencia SELECT permite eliminar filas duplicadas añadiendo la cláusula DISTINT:
sqlite> SELECT DISTINCT referencia FROM pedidos; referencia 123 125 126 132 154 178 180 sqlite>