¿Como hacer consultas simples (en una tabla) con PostgreSQL y SQLite?
En este documento voy a mostrar las bases de las consultas SQL en una tabla simple. Voy a utilizar principalmente PostgreSQL, pero cuando existan diferencias, mostraré tambien la versión SQLite.
La consulta más simple consiste en el uso de las clausulas SELECT y FROM
SELECT pais, superficie_km2
FROM countries;| pais | superficie_km2 |
|---|---|
| Chile | 756626 |
| Colombia | 1142000 |
| Francia | 549134 |
Notas: las variables en SELECT están separadas por coma, y la consulta termina por ;
*Para evitar de escribir todas las variables de una tabla, podemos utilizar “*“:
SELECT *
FROM countries;| pais | sur_america | superficie_km2 |
|---|---|---|
| Chile | TRUE | 756626 |
| Colombia | TRUE | 1142000 |
| Francia | FALSE | 549134 |
SQL es sensible al uso de las mayúsculas y minúsculas, sin embargo, los nombres de las clausulas se pueden escribir de cualquier manera. Usualmente las escribemos en mayuscula, para que las consultas sean más claras para leer…
select *
frOm countries;| pais | sur_america | superficie_km2 |
|---|---|---|
| Chile | TRUE | 756626 |
| Colombia | TRUE | 1142000 |
| Francia | FALSE | 549134 |
"En SQL, los nombres de los objetos deberían escribirse con comillas:
SELECT "pais", "superficie_km2"
FROM "countries";| pais | superficie_km2 |
|---|---|
| Chile | 756626 |
| Colombia | 1142000 |
| Francia | 549134 |
Sin embargo, todo como funciona como si el sistema pasaría todo a minúsculas cuando no utilizamos las comillas.
SELECT PaIs, SuPerficie_km2
FROM countries;| pais | superficie_km2 |
|---|---|
| Chile | 756626 |
| Colombia | 1142000 |
| Francia | 549134 |
Así que si cambiamos mayusculas y minusculas en una consulta con comillas ", obtenemos un error (el error depende del sistema y de la interfaz que utilicen).
Pueden intentar eso en DBeaver con postgreSQL
SELECT "PaIs","Superficie_km2"
FROM countries;En SQLite, no van a tener un error!
Por utilizar la clausula AS, pueden cambiar los nombres de las columnas en las clausulas
SELECT pais, superficie_km2 AS "¿Que tan grande es?, digamos... ¿en km2?"
FROM countries;| pais | ¿Que tan grande es?, digamos… ¿en km2? |
|---|---|
| Chile | 756626 |
| Colombia | 1142000 |
| Francia | 549134 |
Realmente, la clausula AS es facultativa:
SELECT pais tierra, superficie_km2 km2
FROM countries;| tierra | km2 |
|---|---|
| Chile | 756626 |
| Colombia | 1142000 |
| Francia | 549134 |
Existe una noción en PostgreSQL que es el “schema”. Las tablas se pueden organizar en diferentes partes en la base de datos, cada una de esas partes es un “schema”.
Así que la manera completa de llamar una tabla en una clausula FROM es “nombre_schema”.”nombre_tabla”. Sin embargo existe una forma para que PostgreSQL busque automáticamente los nombres de las tablas en uno o varios schema.
Por defecto, el schema “public” está configurado así, y la tabla “countries” está en este schema.
SELECT pais tierra, superficie_km2 km2
FROM countries;| tierra | km2 |
|---|---|
| Chile | 756626 |
| Colombia | 1142000 |
| Francia | 549134 |
En SQLite, no existen los schemas, si uno quiere separar las tablas, tiene que utilizar varios archivos (¡pero es posible trabajar en varios archivos en una misma sesión!)
Todos los datos que utilizamos en SELECT no tienen que estar en una tabla de la base de datos
Podemos añadir una columna con el contenido que queremos
SELECT *, 12 AS mi_numero_favorito
FROM countries;| pais | sur_america | superficie_km2 | mi_numero_favorito |
|---|---|---|---|
| Chile | TRUE | 756626 | 12 |
| Colombia | TRUE | 1142000 | 12 |
| Francia | FALSE | 549134 | 12 |
'En SQL, para diferenciar los objetos de las cadenas de carácter, utilizamos las comillas ' para esas ultimas.
SELECT *, 'lo que quiera' AS "Puedo añadir"
FROM countries;| pais | sur_america | superficie_km2 | Puedo añadir |
|---|---|---|---|
| Chile | TRUE | 756626 | lo que quiera |
| Colombia | TRUE | 1142000 | lo que quiera |
| Francia | FALSE | 549134 | lo que quiera |
SELECT *, superficie_km2/2 mitad
FROM countries;| pais | sur_america | superficie_km2 | mitad |
|---|---|---|---|
| Chile | TRUE | 756626 | 378313 |
| Colombia | TRUE | 1142000 | 571000 |
| Francia | FALSE | 549134 | 274567 |
||El operador || permite pegar (“concatenar”) cadenas de caracter:
La tabla espeletia contiene la taxonomía del genero Espeletia para Colombia
SELECT *
FROM espeletia;| rank | genus | spec_epith | subsp | var | form |
|---|---|---|---|---|---|
| FORM | Espeletia | almorzana | NA | NA |
|
| FORM | Espeletia | argentea | NA | NA |
|
| FORM | Espeletia | brassicoidea | NA | NA |
|
| FORM | Espeletia | brassicoidea | NA | NA |
|
| FORM | Espeletia | brassicoidea | NA | NA | fo. contracta |
| FORM | Espeletia | grandiflora | NA | NA |
|
| FORM | Espeletia | grandiflora | NA | NA |
|
| FORM | Espeletia | grandiflora | NA | NA | fo. longiligulata |
| FORM | Espeletia | grandiflora | NA | NA | fo. multiflora |
| FORM | Espeletia | grandiflora | NA | NA | fo. reducta |
Podemos concatenar las columnas genus y spec_epith para obtener los nombres de especies:
SELECT *, genus ||' '|| spec_epith species
FROM espeletia;| rank | genus | spec_epith | subsp | var | form | species |
|---|---|---|---|---|---|---|
| FORM | Espeletia | almorzana | NA | NA |
|
Espeletia almorzana |
| FORM | Espeletia | argentea | NA | NA |
|
Espeletia argentea |
| FORM | Espeletia | brassicoidea | NA | NA |
|
Espeletia brassicoidea |
| FORM | Espeletia | brassicoidea | NA | NA |
|
Espeletia brassicoidea |
| FORM | Espeletia | brassicoidea | NA | NA | fo. contracta | Espeletia brassicoidea |
| FORM | Espeletia | grandiflora | NA | NA |
|
Espeletia grandiflora |
| FORM | Espeletia | grandiflora | NA | NA |
|
Espeletia grandiflora |
| FORM | Espeletia | grandiflora | NA | NA | fo. longiligulata | Espeletia grandiflora |
| FORM | Espeletia | grandiflora | NA | NA | fo. multiflora | Espeletia grandiflora |
| FORM | Espeletia | grandiflora | NA | NA | fo. reducta | Espeletia grandiflora |
En postgreSQL y SQLite, la clausula FROM no es obligatoría (Nota: no es el caso en todos los “sabores” de SQL)
SELECT '¡Viene de mi cerebro, no de una tabla!' AS "frase cualquiera";| frase cualquiera |
|---|
| ¡Viene de mi cerebro, no de una tabla! |
La clausula FROM usualmente contiene una tabla de la base de datos, pero no es una regla stricta, se pueden utilizar otras cosas.
Para mostrar un caso extremo en PostgreSQL (¡no funciona en SQLite!):
SELECT *
FROM (VALUES('a',1),('b',2),('c',3)) AS tabla(letra, numero);| letra | numero |
|---|---|
| a | 1 |
| b | 2 |
| c | 3 |
La clausula WHERE permite filtrar las filas de una tabla, acepta tipos booleanos:
SELECT *
FROM countries
WHERE sur_america;| pais | sur_america | superficie_km2 |
|---|---|---|
| Chile | TRUE | 756626 |
| Colombia | TRUE | 1142000 |
Si WHERE acepta tipos booleanos, también se pueden utilizar operadores de comparación booleanos(postgreSQL, SQLite
SELECT *
FROM countries
WHERE superficie_km2 < 1000000;| pais | sur_america | superficie_km2 |
|---|---|---|
| Chile | TRUE | 756626 |
| Francia | FALSE | 549134 |
=SELECT *
FROM countries
WHERE pais = 'Chile';| pais | sur_america | superficie_km2 |
|---|---|---|
| Chile | TRUE | 756626 |
<> “es diferente de”SELECT *
FROM countries
WHERE pais <> 'Chile';| pais | sur_america | superficie_km2 |
|---|---|---|
| Colombia | TRUE | 1142000 |
| Francia | FALSE | 549134 |
INSELECT *
FROM countries
WHERE pais IN ('Chile', 'Francia');| pais | sur_america | superficie_km2 |
|---|---|---|
| Chile | TRUE | 756626 |
| Francia | FALSE | 549134 |
Se pueden utilizar operadores booleanos) para combinar condiciones:
SELECT *
FROM countries
WHERE sur_america AND superficie_km2 < 1000000;| pais | sur_america | superficie_km2 |
|---|---|---|
| Chile | TRUE | 756626 |
Los resultados de una consulta se pueden ordenar con la clausula ORDER BY
Esta clausula puede tener las opciones DESC (descending) y ASC (ascending).
SELECT *
FROM countries
ORDER BY superficie_km2 ASC;| pais | sur_america | superficie_km2 |
|---|---|---|
| Francia | FALSE | 549134 |
| Chile | TRUE | 756626 |
| Colombia | TRUE | 1142000 |
SELECT *
FROM countries
ORDER BY superficie_km2 DESC;| pais | sur_america | superficie_km2 |
|---|---|---|
| Colombia | TRUE | 1142000 |
| Chile | TRUE | 756626 |
| Francia | FALSE | 549134 |
Se pueden hacer sorteos complejos asociando varias variables
SELECT *
FROM countries
ORDER BY sur_america,superficie_km2 DESC;| pais | sur_america | superficie_km2 |
|---|---|---|
| Francia | FALSE | 549134 |
| Colombia | TRUE | 1142000 |
| Chile | TRUE | 756626 |
En las bases de datos SQL, el orden del los datos usualmente no es fijo, depende en parte de las estadísticas de uso de los datos. Entonces, cuidado, ¡applicar dos veces la misma consulta no resulta siempre en el mismo resultado en terminos de sorteo!
Siempre se puede limitar el numero de resultados en una consulta, para eso se utiliza la clausula LIMIT.
Es una buena practica utilizar LIMIT para probar algunas consultas largas y complejas, para averiguar que los resultados parecen a lo que queremos.
SELECT *
FROM countries
LIMIT 2;| pais | sur_america | superficie_km2 |
|---|---|---|
| Chile | TRUE | 756626 |
| Colombia | TRUE | 1142000 |
Las funciones agregrativas permiten tratar información sobre más de un registro (una fila) de una tabla. ## COUNT
COUNT permite contar las filas.
SELECT count(pais) num_pais
FROM countries;| num_pais |
|---|
| 3 |
Esa consulta puede parecer un poco rara: ¿para que contar las filas de la columna país? y no de la tabla completa.
Es cierto, poner el nombre de la columna tiene mucho más sentido cuando se utiliza con otras clausulas como DISTINCT o FILTER (que vamos a ver más tarde).
Por esa razon tambien se utiliza seguido el *:
SELECT count(*)
FROM countries
WHERE sur_america;| count |
|---|
| 2 |
Podemos asociar todas las funciones agregativas con una clausula GROUP BY que permite agrupar las filas.
La tabla de resultados tiene una fila por asociación unica de los valores que están en la clausula GROUP BY.
Tambien es importante saber que cuando utilizamos la clausula GROUP BY, la clausula SELECT solo acepta las variables que están en la clausula GROUP BY o funciones agregativas.
Por ejemplo la tabla bogota_chingaza es un ejemplo simplificado de tabla de abundancia de especies en un formato de base de datos:
SELECT *
FROM bogota_chingaza;| unidad_muestreo | especie | abundancia |
|---|---|---|
| Bogotá | Canis lupus | 3000 |
| Bogotá | Felis catus | 1000 |
| Chingaza | Tremarctos ornatus | 50 |
| Chingaza | Canis lupus | 100 |
| Chingaza | Odocoileus virginianus | 200 |
Para calcular el numero de especies por sitio:
SELECT unidad_muestreo,count(especie)
FROM bogota_chingaza
GROUP BY unidad_muestreo;| unidad_muestreo | count |
|---|---|
| Bogotá | 2 |
| Chingaza | 3 |
Para calcular la suma de individuo por especie
SELECT especie ,sum(abundancia)
FROM bogota_chingaza
GROUP BY especie;| especie | sum |
|---|---|
| Tremarctos ornatus | 50 |
| Odocoileus virginianus | 200 |
| Canis lupus | 3100 |
| Felis catus | 1000 |
Para calcular el promedio de abundancia de las especies en cada unidad de muestreo
SELECT unidad_muestreo ,AVG(abundancia)
FROM bogota_chingaza
GROUP BY unidad_muestreo;| unidad_muestreo | avg |
|---|---|
| Bogotá | 2000.0000 |
| Chingaza | 116.6667 |
Tambien se puede agregar el texto de varios filas en asociación con GROUP BY
SELECT unidad_muestreo , STRING_AGG(especie, ', ') list_esp
FROM bogota_chingaza
GROUP BY unidad_muestreo;| unidad_muestreo | list_esp |
|---|---|
| Bogotá | Canis lupus, Felis catus |
| Chingaza | Tremarctos ornatus, Canis lupus, Odocoileus virginianus |
En postgreSQL existe una clase de objetos particulares que se llama “ARRAY” (https://www.postgresql.org/docs/current/arrays.html).
Podemos aggregar un array en asociación con la clausula GROUP BY:
SELECT especie , ARRAY_AGG(abundancia) list_abund
FROM bogota_chingaza
GROUP BY especie;| especie | list_abund |
|---|---|
| Tremarctos ornatus | {50} |
| Odocoileus virginianus | {200} |
| Canis lupus | {3000,100} |
| Felis catus | {1000} |
La clausula WHERE no funciona para probar condiciones sobre los valores agregados: hay que utilizar la clausula HAVING
SELECT especie , SUM(abundancia) tot_abund
FROM bogota_chingaza
GROUP BY especie
HAVING SUM(abundancia) >= 1000
;| especie | tot_abund |
|---|---|
| Canis lupus | 3100 |
| Felis catus | 1000 |