Saltar a contenido

2 – Consultas en PostgreSQL

Consultas básicas: SELECT

Devuelve todas las filas y columnas:

SELECT * FROM empleados;

Puedes seleccionar columnas concretas:

SELECT nombre, edad FROM empleados;

Alias de columnas

Los alias permiten renombrar columnas en la salida:

SELECT
    nombre AS "Nombre completo",
    salario * 1.1 AS "Salario con subida"
FROM empleados;

Se puede usar AS, aunque es opcional. Si el alias tiene espacios o mayúsculas, hay que usar comillas dobles.

Alias de tablas

Útiles en consultas con múltiples tablas o JOINs:

SELECT
    e.nombre, 
    d.nombre_departamento
FROM
    empleados AS e
JOIN departamentos AS d
    ON e.id_departamento = d.id_departamento;

Cláusula WHERE

Filtra los resultados según condiciones.

SELECT nombre FROM empleados WHERE edad > 30;

Operadores habituales

Operador Uso
= Igual a
<> o != Distinto de
<, >, <=, >= Comparaciones numéricas
BETWEEN Rango de valores
IN Coincidencia en una lista
LIKE Patrón textual (%, _)
IS NULL Es nulo
IS NOT NULL No es nulo

Ordenación y límites: ORDER BY y LIMIT

Ordena el resultado:

SELECT * FROM empleados ORDER BY edad;

Por defecto es ascendente (ASC).
Descendente:

ORDER BY edad DESC

También puedes ordenar por el número de columna:

SELECT
    nombre,
    salario
FROM
    empleados
ORDER BY
    2 DESC;

Restringe el número de filas devueltas:

SELECT
    *
FROM
    empleados
ORDER BY
    salario DESC
LIMIT 3;

Empleado con salario más alto:

SELECT
    nombre,
    salario
FROM
    empleados
ORDER BY
    salario DESC
LIMIT 1;

Empleado más joven:

SELECT
    nombre,
    edad
FROM
    empleados
ORDER BY
    edad ASC
LIMIT 1;

Tipos de JOIN

Tablas de ejemplo

id_producto nombre_producto
1 Camiseta
2 Pantalón
3 Zapatos
id_color nombre_color
1 Rojo
2 Azul

INNER JOIN

Solo coincidencias.

SELECT
    *
FROM
    productos
    INNER JOIN colores
        ON productos.id_producto = colores.id_color;

LEFT JOIN

Muestra todos los productos, aunque no tengan color asociado.

SELECT
    *
FROM
    productos
    LEFT JOIN colores
        ON productos.id_producto = colores.id_color;

Filtrar productos sin color asignado:

SELECT
    *
FROM
    productos
    LEFT JOIN colores
        ON productos.id_producto = colores.id_color
WHERE
    colores.id_color IS NULL;

RIGHT JOIN

Muestra todos los colores, aunque no tengan producto asociado.

SELECT
    *
FROM
    productos
    RIGHT JOIN colores
        ON productos.id_producto = colores.id_color;

FULL JOIN

Devuelve todas las filas de ambas tablas, coincidan o no.

SELECT
    *
FROM
    productos
    FULL JOIN colores
        ON productos.id_producto = colores.id_color;

CROSS JOIN

Producto cartesiano: todas las combinaciones posibles (3 × 2 = 6 filas).

SELECT
    *
FROM
    productos
    CROSS JOIN colores;
JOIN ¿Qué hace?
FULL JOIN Une filas coincidentes y muestra también las no relacionadas
CROSS JOIN Todas las combinaciones posibles (producto cartesiano)

Funciones de agregación

id nombre edad salario departamento
1 Ana 25 1200 Ventas
2 Luis 45 1800 Marketing
3 Marta 30 1500 Ventas
4 Pedro 50 2200 Marketing
5 Clara 29 1600 Ventas
SELECT COUNT(*) FROM empleados;             -- 5
SELECT SUM(salario) FROM empleados;         -- 8300
SELECT AVG(salario) FROM empleados;         -- 1660
SELECT MIN(edad), MAX(edad) FROM empleados; -- 25 y 50

Agrupación: GROUP BY

SELECT
    departamento,
    COUNT(*) 
FROM
    empleados 
GROUP BY
    departamento;

Regla: todos los campos que están en GROUP BY deben aparecer en el SELECT, salvo funciones de agregación.

SELECT
    departamento,
    AVG(salario) 
FROM
    empleados 
GROUP BY
    departamento;
departamento AVG(salario)
Ventas 1433.33
Marketing 2000.00

HAVING vs WHERE

Cláusula Filtra… Cuándo se aplica
WHERE Filas individuales Antes del GROUP BY
HAVING Grupos agregados Después del GROUP BY
SELECT
    nombre,
    salario
FROM
    empleados
WHERE
    salario > 1500;

Filtra empleados individuales cuyo salario es mayor a 1500.

SELECT
    departamento,
    COUNT(*) AS empleados
FROM
    empleados
GROUP BY
    departamento
HAVING COUNT(*) > 2;

Filtra grupos (departamentos) que tienen más de 2 empleados.

Subconsultas

En WHERE (subconsulta NO correlacionada)

SELECT
    nombre
FROM
    empleados
WHERE
    salario > (
        SELECT AVG(salario) FROM empleados
);

Compara con el promedio general.

En SELECT

SELECT
    nombre, 
    (
        SELECT
            AVG(edad)
        FROM
            empleados
    ) AS edad_media
FROM
    empleados;

Agrega la media a cada fila.

En FROM

SELECT
    departamento,
    total
FROM
  (
      SELECT
          departamento,
          COUNT(*) AS total
      FROM
          empleados
      GROUP BY
          departamento
  ) AS resumen
WHERE
    total > 2;

Subconsulta correlacionada vs no correlacionada

No correlacionada:

SELECT
    nombre
FROM
    empleados
WHERE
    salario > (SELECT AVG(salario) FROM empleados);

No depende de la fila externa.

Correlacionada:

SELECT
    e.nombre
FROM
    empleados e
WHERE
    salario > (
        SELECT
            AVG(salario)
        FROM
            empleados
        WHERE
            departamento = e.departamento
);

Compara con el promedio del mismo departamento.