Kodokon kodokon.com

Subconsultas: WHERE, FROM, IN y EXISTS

Anida una consulta dentro de otra para comparar con un agregado, filtrar por un conjunto o comprobar la existencia.

9 min · 3 preguntas

Abrir esta lección en Kodokon

Una subconsulta es una consulta colocada entre paréntesis dentro de otra. En una sola instrucción responde preguntas como "los pedidos por encima de la media" o "los clientes con al menos un pedido". Ejecuta este script en sqliteonline.com o sqlite3 antes de empezar.

SQL
CREATE TABLE customers (
  id INTEGER PRIMARY KEY,
  name TEXT NOT NULL
);

CREATE TABLE orders (
  id INTEGER PRIMARY KEY,
  customer_id INTEGER NOT NULL,
  amount REAL NOT NULL
);

INSERT INTO customers (id, name) VALUES
  (1, 'Alice'), (2, 'Karim'),
  (3, 'Mina'), (4, 'Paulo');

INSERT INTO orders (id, customer_id, amount)
VALUES
  (1, 1, 49.90), (2, 1, 15.00),
  (3, 2, 120.50), (4, 2, 80.00),
  (5, 3, 9.90), (6, 1, 200.00);
Conjunto de datos: cuatro clientes, seis pedidos.

Colocada en WHERE, una subconsulta escalar debe devolver un único valor: una fila, una columna. El motor la calcula primero y luego la usa como cualquier otra constante. No puedes hacer esto con un simple WHERE amount > AVG(amount), que está prohibido en SQL.

SQL
SELECT id, customer_id, amount
FROM orders
WHERE amount > (
  SELECT AVG(amount) FROM orders
);
Los pedidos por encima de la cesta media (79.22).

IN compara una columna con el conjunto de valores que devuelve la subconsulta. EXISTS comprueba si la subconsulta correlacionada (hace referencia a c.id, una columna de la consulta externa) devuelve al menos una fila: el motor se detiene en cuanto encuentra la primera coincidencia.

SQL
SELECT name FROM customers
WHERE id IN (
  SELECT customer_id FROM orders
  WHERE amount > 100
);

SELECT c.name FROM customers AS c
WHERE EXISTS (
  SELECT 1 FROM orders AS o
  WHERE o.customer_id = c.id
);
IN: los que más gastan. EXISTS: los clientes activos.

En FROM, una subconsulta se comporta como una tabla temporal, llamada tabla derivada, y debe recibir un alias. Es la herramienta clásica para agregar en dos pasos: primero un total por cliente, luego la media de esos totales.

SQL
SELECT ROUND(AVG(t.total), 2) AS avg_basket
FROM (
  SELECT customer_id, SUM(amount) AS total
  FROM orders
  GROUP BY customer_id
) AS t;
Cesta total media por cliente activo: 158.43.

Prueba de conocimientos

Comprueba que has retenido los puntos clave de esta lección.

  1. ¿Cuántos valores debe devolver una subconsulta usada en amount > (...)?
    • Exactamente uno
    • Uno por cada fila de la tabla externa
    • Tantos como quiera
  2. ¿Cuál es la principal ventaja de EXISTS sobre IN?
    • Puede devolver varias columnas
    • Se detiene en la primera fila encontrada, sin materializar todo el conjunto
    • Funciona sin subconsulta
  3. ¿Qué debe llevar siempre una subconsulta colocada en FROM para ser portable en todas partes?
    • Un alias, como AS t
    • Una cláusula ORDER BY
    • Un punto y coma interno