Blog · 20 de julio de 2026

Subconsultas en SQL: qué son, tipos y cuándo usarlas (con ejemplos)

Guía práctica de subconsultas SQL: escalares, IN/ANY/ALL, correlacionadas con EXISTS y tablas derivadas. Con ejemplos y ejercicios interactivos gratis.

Si llevas un tiempo escribiendo consultas SQL, tarde o temprano te topas con una pregunta que un SELECT simple no puede responder: "¿qué empleados ganan más que el promedio?", "¿qué clientes nunca han comprado?". Para responderlas necesitas que una consulta use el resultado de otra consulta. Eso es, exactamente, una subconsulta.

En esta guía vas a ver qué son, los cuatro tipos que existen, cuándo conviene usarlas (y cuándo conviene un JOIN), con ejemplos que puedes ejecutar gratis en tu navegador.

Qué es una subconsulta

Una subconsulta (también llamada consulta anidada o subquery) es un SELECT escrito dentro de otra sentencia SQL, siempre entre paréntesis. El motor ejecuta primero la consulta interior y usa su resultado en la exterior.

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

Aquí la subconsulta (SELECT AVG(salario) FROM empleados) calcula el salario promedio, y la consulta exterior lo usa como si fuera un número: "dame los empleados que ganan más que ese valor". Intentar esto sin subconsulta (WHERE salario > AVG(salario)) da error — las funciones de agregación no se pueden usar directo en el WHERE.

Los 4 tipos de subconsulta

La forma más útil de clasificarlas es por lo que devuelven, porque eso determina dónde puedes usarlas:

Tipo Devuelve Se usa típicamente con
Escalar Un solo valor (1 fila, 1 columna) =, >, <, operaciones
De lista Una columna con varias filas IN, NOT IN, ANY, ALL
Correlacionada Depende de cada fila exterior EXISTS, NOT EXISTS
Tabla derivada Una tabla completa En el FROM

Veamos cada una con un ejemplo real.

1. Subconsulta escalar: un solo valor

Devuelve exactamente una fila con una columna, así que puedes usarla en cualquier lugar donde iría un número o un texto: en el WHERE, en el SELECT, hasta en un cálculo.

-- ¿Qué productos cuestan más que el precio promedio?
SELECT nombre, precio
FROM productos
WHERE precio > (SELECT AVG(precio) FROM productos);
-- Mostrar cada salario junto con la diferencia contra el máximo
SELECT nombre,
       salario,
       (SELECT MAX(salario) FROM empleados) - salario AS diferencia_con_el_top
FROM empleados;

Ojo: si la subconsulta escalar devuelve más de una fila, el motor lanza un error. Si eso te pasa, probablemente necesitabas IN en vez de =.

2. Subconsultas con IN, NOT IN, ANY y ALL

Cuando la subconsulta devuelve una lista de valores, se combina con operadores de conjunto:

-- Clientes que SÍ han hecho pedidos
SELECT nombre
FROM clientes
WHERE id IN (SELECT DISTINCT cliente_id FROM pedidos);
-- Clientes que NUNCA han comprado (el clásico de las entrevistas)
SELECT nombre
FROM clientes
WHERE id NOT IN (SELECT cliente_id FROM pedidos WHERE cliente_id IS NOT NULL);

El IS NOT NULL de la segunda consulta no es decorativo: si la lista de un NOT IN contiene un NULL, el resultado completo queda vacío. Es uno de los errores más traicioneros de SQL.

ANY y ALL comparan contra la lista con un operador:

-- Productos más caros que TODOS los de la categoría 'Accesorios'
SELECT nombre, precio
FROM productos
WHERE precio > ALL (SELECT precio FROM productos WHERE categoria = 'Accesorios');

> ANY significa "mayor que al menos uno" (equivale a > MIN(...)), y > ALL significa "mayor que todos" (equivale a > MAX(...)).

3. Subconsultas correlacionadas y EXISTS

Las anteriores se ejecutan una sola vez. Una subconsulta correlacionada hace referencia a la fila de la consulta exterior, así que se evalúa para cada fila:

-- Empleados que ganan más que el promedio DE SU PROPIO departamento
SELECT nombre, departamento, salario
FROM empleados e
WHERE salario > (SELECT AVG(salario)
                 FROM empleados
                 WHERE departamento = e.departamento);

La pista para reconocerlas: la consulta interior usa el alias de la exterior (e.departamento). Su pareja natural es EXISTS, que solo pregunta "¿hay al menos una fila que cumpla?" sin traer datos:

-- Clientes con al menos un pedido completado
SELECT nombre
FROM clientes c
WHERE EXISTS (SELECT 1
              FROM pedidos p
              WHERE p.cliente_id = c.id
                AND p.estado = 'Completado');

NOT EXISTS es además la forma más segura de expresar "que no tengan...": no sufre el problema del NULL que vimos con NOT IN.

4. Tablas derivadas: subconsultas en el FROM

Una subconsulta en el FROM crea una tabla temporal con nombre que puedes consultar como cualquier otra:

-- Promedio de ventas por cliente, calculado en dos pasos
SELECT AVG(total_por_cliente) AS promedio_general
FROM (SELECT cliente_id, SUM(total) AS total_por_cliente
      FROM pedidos
      GROUP BY cliente_id) AS ventas;

El alias (AS ventas) es obligatorio. Cuando estas tablas derivadas se anidan demasiado y la consulta se vuelve ilegible, la evolución natural son los CTE (WITH ... AS), que hacen lo mismo con nombres declarados arriba — pero ese tema merece su propio artículo.

¿Subconsulta o JOIN?

Casi toda subconsulta puede reescribirse como JOIN y viceversa. Una guía práctica para decidir:

Errores comunes (repaso rápido)

Practícalo ahora, gratis y sin instalar nada

La teoría se fija escribiendo consultas. En mi curso interactivo Aprende SQL hay un módulo completo de subconsultas con ejercicios autocorregidos que corren en tu navegador (SQLite real, sin registro):

Cada lección trae 3 ejercicios (básico, intermedio y reto) sobre un dataset de empresa realista, y un copiloto de IA te da pistas si te trabas. Empieza por la 22 y en una tarde las subconsultas dejan de ser un misterio.

Ver todos los artículos →