Lesión 6.2 · Tiempo de lectura: ~8 min
Una subconsulta en WHERE te permite filtrar filas basadas en el resultado intermedio de otra consulta. En esta lección, aprenderás cuándo usar operadores de comparación, IN, NOT IN, EXISTS, NOT EXISTS, ANY y ALL, y cómo elegir la opción más segura para tareas prácticas.
Subconsultas en la cláusula WHERE
En la lección anterior, cubrimos la idea general de las subconsultas. Ahora nos enfocamos en el escenario más común: filtrar en WHERE, cuando la consulta externa depende de valores calculados dinámicamente.
En el trabajo real, esto se utiliza constantemente: desde encontrar clientes sin pagos hasta comparar una fila contra un conjunto de resultados.
Subconsultas escalares y operadores de comparación
Si una subconsulta devuelve exactamente un valor, se llama subconsulta escalar. En ese caso, puedes usar operadores estándar =, <>, >, >=, <, <=.
Escenario: encontrar actores con el mismo nombre de pila que el actor con actor_id = 10.
SELECT
first_name,
last_name
FROM
actor
WHERE
first_name = (
SELECT first_name
FROM actor
WHERE actor_id = 10
)
AND actor_id <> 10;
Nota: si la consulta interna devuelve múltiples filas, esta consulta falla con un error.
Subconsultas de múltiples filas: IN y NOT IN
Cuando una subconsulta devuelve una lista de valores (una columna, muchas filas), usa IN.
Escenario: encontrar películas en la categoría Acción.
SELECT
f.title
FROM
film AS f
WHERE
f.film_id IN (
SELECT
fc.film_id
FROM
film_category AS fc
WHERE
fc.category_id = (
SELECT
c.category_id
FROM
category AS c
WHERE
c.name = 'Acción'
)
);
Resultado: obtienes todas las películas vinculadas a la categoría Acción a través de la tabla film_category.
NOT IN realiza el filtrado opuesto, pero recuerda una advertencia importante: si el resultado de la subconsulta contiene NULL, la condición puede producir un resultado inesperadamente vacío. En estos casos, NOT EXISTS es a menudo más seguro.
Comprobaciones de existencia: EXISTS y NOT EXISTS
EXISTS verifica si al menos una fila existe en la subconsulta. La base de datos puede detenerse en la primera coincidencia, por lo que este enfoque es a menudo eficiente en tablas grandes.
EXISTS
Escenario: encontrar clientes que tienen al menos un pago.
SELECT
c.first_name,
c.last_name
FROM
customer AS c
WHERE
EXISTS (
SELECT
1
FROM
payment AS p
WHERE
p.customer_id = c.customer_id
);
Nota: con EXISTS, SELECT 1 se usa comúnmente porque solo importa la existencia de la fila, no los valores de las columnas devueltas.
NOT EXISTS
Escenario: encontrar clientes que no han realizado ningún pago.
SELECT
c.first_name,
c.last_name
FROM
customer AS c
WHERE
NOT EXISTS (
SELECT
1
FROM
payment AS p
WHERE
p.customer_id = c.customer_id
);
Resultado: solo se devuelven los clientes sin filas coincidentes en payment.
Comparando contra un conjunto: ANY y ALL
ANY: la condición es verdadera si es verdadera para al menos un valor de la subconsulta.ALL: la condición es verdadera solo si es verdadera para cada valor de la subconsulta.
Escenario: comparar la longitud de la película con las longitudes de las películas en la categoría Comedia.
SELECT
f.title,
f.length
FROM
film AS f
WHERE
f.length > ANY (
SELECT
f2.length
FROM
film AS f2
INNER JOIN film_category AS fc ON f2.film_id = fc.film_id
INNER JOIN category AS c ON fc.category_id = c.category_id
WHERE
c.name = 'Comedia'
);
Resultado: una película se incluye si es más larga que al menos una película en Comedia.
SELECT
f.title,
f.length
FROM
film AS f
WHERE
f.length > ALL (
SELECT
f2.length
FROM
film AS f2
INNER JOIN film_category AS fc ON f2.film_id = fc.film_id
INNER JOIN category AS c ON fc.category_id = c.category_id
WHERE
c.name = 'Comedia'
);
Resultado: una película se incluye solo si es más larga que cada película en Comedia.
Qué observar en consultas reales
- Para un solo valor, usa una subconsulta escalar con un operador de comparación.
- Para una lista de valores, usa
INoEXISTSdependiendo de la tarea. - Para encontrar relaciones faltantes, prefiere
NOT EXISTS, especialmente cuando los valoresNULLson posibles. - Siempre verifica si una subconsulta puede devolver más filas de las esperadas.
Conclusiones clave de esta lección:
WHEREcon subconsultas permite un filtrado dinámico sin sustitución manual de valores.INes conveniente para verificar la pertenencia a una lista de valores.EXISTSyNOT EXISTSson efectivos para probar la presencia y ausencia de filas relacionadas.ANYyALLte permiten comparar una fila contra un conjunto completo de valores.- Elegir el operador correcto hace que las consultas sean más precisas, legibles y confiables.
Preguntas Frecuentes
¿Cuál es mejor para encontrar relaciones faltantes: NOT IN o NOT EXISTS?
En la mayoría de las tareas prácticas, NOT EXISTS es más seguro. Si una subconsulta NOT IN devuelve NULL, el resultado puede volverse inesperado y filtrar demasiadas filas.
¿Por qué la gente suele escribir SELECT 1 en EXISTS en lugar de SELECT *?
Porque EXISTS solo verifica si las filas existen. Los valores de las columnas seleccionadas no se utilizan, por lo que SELECT 1 es una forma estándar y clara.
¿Cuándo debo usar ANY y cuándo debo usar ALL?
Usa ANY cuando la condición debe ser verdadera para al menos un valor de la subconsulta. Usa ALL cuando la condición debe ser verdadera para cada valor en el conjunto.
Preguntas de Entrevista
¿Cuál es la diferencia entre IN y EXISTS en SQL?
IN compara un valor con una lista devuelta por una subconsulta, mientras que EXISTS verifica si hay al menos una fila coincidente. En conjuntos de datos grandes, EXISTS es a menudo más eficiente en patrones correlacionados porque puede detenerse en la primera coincidencia.
¿Cómo explicarías la diferencia entre subconsultas escalares y de múltiples filas?
Una subconsulta escalar devuelve un valor y se usa con operadores como = o >. Una subconsulta de múltiples filas devuelve un conjunto de valores y se usa generalmente con IN, ANY o ALL.
¿Por qué puede fallar una consulta con el operador = y una subconsulta?
El operador = espera un solo valor en el lado derecho. Si la subconsulta devuelve más de una fila, el motor SQL no puede realizar una comparación inequívoca y genera un error.
En la próxima lección, veremos subconsultas correlacionadas y cómo se ejecutan fila por fila en la consulta externa.