Tutorial de subconsultas SQL: tipos, subconsultas correlacionadas y EXISTENCIAS con ejemplos

  1. Inicio
  2. Blog
  3. Bases de datos y SQL

Bases de datos y SQL

Tutorial de subconsultas SQL: Tipos, subconsultas correlacionadas y EXISTENCIAS con ejemplos

Una subconsulta es una consulta dentro de otra consulta. Aprenda cada tipo y dónde encaja, comprenda correctamente las subconsultas correlacionadas y evite la trampa NOT IN que silenciosamente no devuelve ninguna fila.

9 min de lectura
Tutorial de subconsultas SQL: tipos, subconsultas correlacionadas y EXISTENTES con ejemplos

Puntos clave

  • Una subconsulta es una consulta anidada dentro de otra y la consulta externa utiliza su resultado.
  • Las subconsultas pueden aparecer en WHERE, FROM, SELECT y HAVING.
  • Una subconsulta correlacionada se refiere a la fila exterior, por lo que se evalúa lógicamente por fila.
  • Prefiera NOT EXISTS a NOT IN cuando sean posibles NULL.

Algunas preguntas requieren dos pasos para responderse. “¿Qué pedidos están por encima del promedio?” requiere que primero encuentre el promedio y luego compare cada orden con él. Subconsultas SQL le permiten escribir ambos pasos como una sola declaración.

Este tutorial cubre cada tipo usando dos tablas pequeñas. Ejecutamos estas consultas en SQLite 3.50 y los resultados mostrados provienen de esa ejecución. La sintaxis de subconsulta estándar es ampliamente compatible y señalamos los lugares donde difieren las bases de datos.

¿Qué es una subconsulta?

Una subconsulta, también llamada consulta interna o anidada, es una declaración SELECT colocada dentro de otra declaración, entre corchetes. Conceptualmente, la consulta interna produce un resultado que luego utiliza la consulta externa.

SELECT id, total
FROM orders
WHERE total > (SELECT AVG(total) FROM orders);

Las tablas de muestra

CREATE TABLE customers (id INT, name TEXT, city TEXT);
CREATE TABLE orders (id INT, customer_id INT, total INT);

INSERT INTO customers VALUES
 (1,'Asha','Pune'), (2,'Ben','Delhi'), (3,'Chitra','Pune'), (4,'Dev','Goa');

INSERT INTO orders VALUES
 (101,1,1200), (102,1,800), (103,2,300), (104,3,2500), (105,3,100);

Tenga en cuenta que Dev no tiene órdenes. Ese detalle es importante para varios ejemplos a continuación.

Tipos de subconsultas de un vistazo

Tipo Devoluciones Ubicación típica Operadores comunes
escalar un valor WHERE, SELECT =, >, <
varias filas Una columna, muchas filas DONDE IN, ANY, ALL
Tabla (derivada) Muchas columnas y filas DESDE Usado como una mesa
correlacionado Depende de la fila exterior WHERE, SELECT Cualquiera y EXISTS

Subconsultas escalares

Una subconsulta escalar devuelve exactamente un valor, por lo que puede usarla siempre que un valor único tenga sentido. Aquí está la consulta anterior, con su resultado. El promedio de todos los pedidos es 980:

SELECT id, total
FROM orders
WHERE total > (SELECT AVG(total) FROM orders);

-- 101 | 1200
-- 104 | 2500

No se pudo escribir WHERE total > AVG(total), porque no se permiten agregados directamente en WHERE. La subconsulta soluciona esto calculando el valor por separado.

¿Qué pasa si una subconsulta “escalar” devuelve varias filas? La mayoría de las bases de datos, incluidas PostgreSQL, MySQL y SQL Server, generan un error. SQLite no lo hace. En nuestra prueba, usó silenciosamente solo la primera fila, lo que podría ocultar un error real, así que no dependa de este comportamiento.

EN y NO EN

Cuando la consulta interna devuelva una lista, utilice IN. Esto encuentra clientes con al menos un pedido superior a 1000:

SELECT name FROM customers
WHERE id IN (SELECT customer_id FROM orders WHERE total > 1000);

-- Asha
-- Chitra

NOT IN hace lo contrario: encuentra clientes que nunca han realizado un pedido:

SELECT name FROM customers
WHERE id NOT IN (SELECT customer_id FROM orders);

-- Dev

Eso funciona aquí, pero NOT IN tiene un caso extremo peligroso, que cubrimos a continuación.

Subconsultas en FROM

Una subconsulta en FROM actúa como una tabla temporal, a menudo denominada tabla derivada. Es útil cuando necesita agregar dos veces, como en esta consulta para el gasto promedio por cliente en cada ciudad:

SELECT city, AVG(spent) AS avg_spent
FROM (
  SELECT c.city, SUM(o.total) AS spent
  FROM customers c
  JOIN orders o ON o.customer_id = c.id
  GROUP BY c.id, c.city
) AS per_customer
GROUP BY city;

-- Delhi |  300.0
-- Pune  | 2300.0

La consulta interna totaliza cada cliente y la externa promedia esos totales. Dar un alias a la tabla derivada es un buen hábito, ya que algunas bases de datos lo requieren. Si GROUP BY es nuevo para usted, consulte SQL GROUP BY y HAVING.

Subconsultas en SELECT

Una subconsulta escalar también puede agregar una columna calculada. Éste cuenta los pedidos por cliente:

SELECT name,
       (SELECT COUNT(*) FROM orders o WHERE o.customer_id = c.id) AS order_count
FROM customers c;

-- Asha   | 2
-- Ben    | 1
-- Chitra | 2
-- Dev    | 0

Dev aparece con cero. Una unión interna habría eliminado a Dev por completo, porque Dev no tiene filas coincidentes. Podrías obtener el mismo resultado con LEFT JOIN y GROUP BY, lo cual explicamos en Explicación de uniones SQL.

Subconsultas correlacionadas

El ejemplo anterior también está correlacionado, ya que la consulta interna hace referencia a c.id de la consulta externa. Una subconsulta no correlacionada puede ejecutarse sola. Uno correlacionado no puede, porque depende de un valor de la fila exterior actual.

Esto encuentra pedidos por encima del promedio del mismo cliente:

SELECT o.id, o.customer_id, o.total
FROM orders o
WHERE o.total > (
  SELECT AVG(i.total)
  FROM orders i
  WHERE i.customer_id = o.customer_id
);

-- 101 | 1 | 1200
-- 104 | 3 | 2500

Aquí se explica cómo leerlo. Para el pedido 101, la consulta interna promedia los pedidos del cliente 1 (1200 y 800), lo que da 1000. Como 1200 es mayor, la fila se mantiene. Para el pedido 102, se aplica el mismo promedio, pero 800 no es mayor, por lo que se descarta. El pedido único del cliente 2 es igual a su propio promedio, por lo que también se descarta.

Característica No correlacionado correlacionado
¿Utiliza valores de consulta externos? No si
¿Puede funcionar solo? si No
Ejecución lógica una vez Una vez por fila exterior
Riesgo de desempeño Generalmente bajo Puede estar alto en mesas grandes.

“Una vez por fila” describe la lógica, y los optimizadores de consultas a menudo las reescriben en algo mucho más eficiente. Aún así, vale la pena investigar una subconsulta correlacionada lenta. Un índice en la columna interior, aquí orders.customer_id, puede marcar una gran diferencia. Consulte Explicación de los índices SQL.

EXISTE y NO EXISTE

EXISTS hace una pregunta de sí o no: ¿la consulta interna devuelve al menos una fila? Puede detenerse en el primer partido y lo que selecciones dentro no importa, razón por la cual la gente suele escribir SELECT 1.

SELECT c.name FROM customers c
WHERE EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.id);

-- Asha, Ben, Chitra

SELECT c.name FROM customers c
WHERE NOT EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.id);

-- Dev

La trampa NO EN NULL

Este es uno de los errores de subconsulta más comunes. Creamos una tabla con una ID real y una NULL, luego ejecutamos ambos formularios en ella:

CREATE TABLE r (customer_id INT);
INSERT INTO r VALUES (1), (NULL);

SELECT name FROM customers
WHERE id NOT IN (SELECT customer_id FROM r);
-- (no rows at all)

SELECT c.name FROM customers c
WHERE NOT EXISTS (SELECT 1 FROM r WHERE r.customer_id = c.id);
-- Ben, Chitra, Dev

¿Por qué el primero no devuelve nada? id NOT IN (1, NULL) significa id <> 1 AND id <> NULL. Cualquier comparación con NULL es más desconocida que verdadera, por lo que toda la condición nunca puede ser verdadera. No hay ningún mensaje de error ni advertencia, solo un resultado vacío que parece plausible.

Consejo: Utilice NOT EXISTS para antiuniones de forma predeterminada. Si usa NOT IN, agregue WHERE customer_id IS NOT NULL dentro de la subconsulta.

Subconsulta vs JOIN vs CTE

Muchas consultas se pueden escribir de más de una manera. Anteriormente encontramos clientes con un pedido grande usando IN. Aquí está el mismo resultado con una unión:

SELECT DISTINCT c.name FROM customers c
JOIN orders o ON o.customer_id = c.id AND o.total > 1000;

-- Asha
-- Chitra

Observe el DISTINCT. Una combinación puede producir duplicados si un cliente tiene varias coincidencias, mientras que IN y EXISTS no pueden.

uso cuando
ÚNETE Necesitas columnas de ambas tablas.
EN o EXISTE Sólo necesitas filtrar si existe una coincidencia.
tabla derivada Primero necesitas agregar y se queda corto.
CTE La lógica tiene varios pasos o se usa más de una vez.
Función de ventana Necesitas una cifra por grupo al lado de cada fila.

El rendimiento varía según la base de datos y los datos, y los optimizadores modernos suelen producir planes similares. Así que elija primero la forma más clara y luego marque EXPLAIN si resulta ser lenta.

Errores comunes

  • Usando = con un resultado de varias filas. Utilice IN o asegúrese de que la consulta interna devuelva una fila.
  • Usando NOT IN en una columna que acepta valores NULL. Puedes perder silenciosamente cada fila.
  • Usar alias poco claros. En consultas correlacionadas, califique cada columna o puede vincularse a la tabla incorrecta.
  • Anidamiento profundo. Tres niveles son difíciles de leer, así que conviértalos a CTE.
  • Agregar ORDER BY adentro. Por lo general, no tiene ningún efecto en el resultado externo y algunas bases de datos lo rechazan.

Conclusión

Las subconsultas son una forma natural de expresar preguntas de dos pasos. Comience con subconsultas escalares y IN, luego practique las correlacionadas razonando a través de una sola fila exterior a la vez. Y recuerde NOT EXISTS siempre que sean posibles NULL. Para practicar, escriba una pregunta de tres maneras, con una subconsulta, una combinación y un CTE, y compare los resultados y la legibilidad.

Preguntas frecuentes

¿Qué es una subconsulta en SQL?

Una subconsulta es una declaración SELECT anidada dentro de otra declaración SQL, entre paréntesis. La declaración externa usa su resultado como un valor, una lista o una tabla.

¿Qué es una subconsulta correlacionada?

Es una subconsulta que hace referencia a una columna de la consulta externa. Depende de la fila exterior actual, por lo que no puede ejecutarse por sí solo.

¿Qué es más rápido, una subconsulta o JOIN?

Depende de la base de datos y de los datos, y los optimizadores suelen producir planes similares. Escriba primero la versión más clara y luego compare los planes de ejecución si el rendimiento importa.

¿Cuál es la diferencia entre EN y EXISTE?

IN compara un valor con una lista de resultados. EXISTS comprueba si se devuelve alguna fila. Se comportan de manera diferente con NULL cuando se niegan.

¿Puede una subconsulta devolver varias columnas?

Sí, cuando se usa en FROM como tabla derivada, y algunas bases de datos también permiten comparaciones de filas. Una subconsulta escalar debe devolver solo una columna y una fila.

sigue aprendiendo

Trabajar con Stack Quora

¿Necesitas ayuda con pruebas, WordPress o SEO?

Ayudamos a los equipos a enviar mejor software y hacer crecer sus sitios. Cuéntenos en qué está trabajando y le sugeriremos un siguiente paso claro.

Sigue leyendo

Más guías sobre testing, IA y desarrollo moderno

¿Te gustó este artículo? Elige un tema y salta directo a nuestros tutoriales más recientes.

Inteligencia artificial

Explicación de las alucinaciones de la IA: por qué los modelos de lenguaje inventan cosas y cómo reducirlas

Se explicaron las alucinaciones de la IA: qué son, por qué los modelos de lenguaje las producen, tipos comunes, cómo reducirlas con conexión a tierr…

Leer artículo →
DevOps

Explicación de las variables de entorno: archivos .env, secretos y configuración bien hechos

Variables de entorno explicadas con ejemplos de Python que ejecutamos: leerlas y configurarlas, por qué cada valor es una cadena, archivos .env, her…

Leer artículo →
Desarrollo de software

Explicación de la limitación de velocidad de API: algoritmos, encabezados y manejo de errores 429

La limitación de la tasa de API se explica con una simulación que ejecutamos: depósito de tokens, ventana fija, ventana deslizante, 429 respuestas, …

Leer artículo →
Automatización de pruebas

Burlarse en Python: unittest.mock, patch y los errores que hacen que las pruebas mientan

Burlarse en Python con unittest.mock, probado: Mock y return_value, side_effect, parches donde se usa un nombre, especificación y autospec, fechas d…

Leer artículo →
Pruebas de software

Explicación de la cobertura del código: cobertura de línea versus sucursal y lo que realmente significa 100%

Cobertura del código explicada con una ejecución real de cobertura.py: cobertura de línea, rama y condición, lectura de un informe, por qué una cobe…

Leer artículo →
Bases de datos y SQL

DELETE vs TRUNCATE vs DROP en SQL: diferencias, reversión y cuándo usar cada uno

DELETE vs TRUNCATE vs DROP explicado con SQL probado: qué elimina cada uno, reversión, activadores, restablecimiento de identidad, velocidad y en qu…

Leer artículo →
Bases de datos y SQL

Vistas SQL explicadas: cree, use y evite los errores, con ejemplos

Vistas SQL explicadas con consultas que ejecutamos: creación de una vista, resultados en vivo, ocultación de columnas, rendimiento, vistas actualiza…

Leer artículo →
Desarrollo de software

Interfaz TypeScript versus tipo: diferencias reales, probadas con el compilador

Interfaz TypeScript versus tipo, verificado con el compilador real: qué pueden hacer ambos, qué puede hacer solo uno, fusión de declaraciones, exten…

Leer artículo →
Desarrollo de software

Python *args y **kwargs explicados: funciones flexibles con ejemplos claros

Python *args y **kwargs explicados con el código que ejecutamos: empaquetado y desempaquetado, orden de parámetros, argumentos solo de palabras clav…

Leer artículo →
Desarrollo de software

Funciones Lambda de Python: sintaxis, usos reales y cuándo no utilizarlas

Funciones lambda de Python explicadas con el código que ejecutamos: sintaxis, clasificación con clave, mapa y filtro, cierres, trampa de enlace tard…

Leer artículo →
Inteligencia artificial

¿Qué son los agentes de IA? Cómo funcionan, con un bucle de agente simple que puedes ejecutar

¿Qué son los agentes de IA? Una guía sencilla sobre el bucle del agente, las herramientas, la memoria y las barreras de seguridad, con un pequeño bu…

Leer artículo →
DevOps

Monitoreo versus observabilidad: la verdadera diferencia, con registros, métricas y seguimientos

Explicación del monitoreo versus observabilidad: fallas conocidas y desconocidas, registros, métricas y seguimientos, un recorrido por incidentes de…

Leer artículo →
DevOps

Docker Volumes versus Bind Mounts: persistir los datos del contenedor de la manera correcta

Se explican los volúmenes de Docker frente a los montajes de enlace: por qué desaparecen los datos del contenedor, volúmenes con nombre, montajes de…

Leer artículo →
Automatización de pruebas

TDD vs BDD: diferencias clave, una función creada en ambos sentidos y cuándo usar cada una

TDD vs BDD explicado con una característica de descuento construida en ambos sentidos: refactor rojo-verde con el código que ejecutamos, escenarios …

Leer artículo →
Pruebas de software

Pruebas de Aceptación de Usuario (UAT): Proceso, Lista de Verificación y Ejemplos Reales

Explicación de las pruebas de aceptación del usuario: quién las ejecuta, en qué se diferencia del control de calidad, un proceso de siete pasos, una…

Leer artículo →
Bases de datos y SQL

Valores NULL de SQL explicados: IS NULL, COALESCE, NULLIF y las trampas que se deben evitar

Los valores NULL de SQL se explican con las consultas que ejecutamos: lógica de tres valores, IS NULL, COALESCE, NULLIF, cómo los agregados, las uni…

Leer artículo →
Bases de datos y SQL

Declaración SQL CASE WHEN: sintaxis, ejemplos reales y errores comunes

CASO SQL CUANDO se explicó con las consultas que ejecutamos: formularios simples y buscados, orden de condiciones, pivotes con SUMA, trucos COUNT, c…

Leer artículo →
Desarrollo de software

¿Qué es JWT? Tokens web JSON explicados con un ejemplo práctico

¿Qué es JWT? JSON Web Tokens explicó: las tres partes, un token creado y manipulado en el código que ejecutamos, JWT vs sesiones, almacenamiento, to…

Leer artículo →
Desarrollo de software

Explicación del bucle de eventos de JavaScript: pila de llamadas, microtareas y temporizadores con ejemplos

El bucle de eventos de JavaScript explicado con el código que ejecutamos: pila de llamadas, colas de tareas y microtareas, por qué setTimeout 0 no e…

Leer artículo →
Desarrollo de software

Explicación de los generadores y el rendimiento de Python: ahorre memoria con ejemplos reales

Los generadores de Python y el rendimiento se explican con el código que ejecutamos: cómo se pausan y reanudan, midieron el ahorro de memoria, canal…

Leer artículo →
Inteligencia artificial

¿Qué son las incrustaciones? Los vectores y la similitud del coseno se explican de forma sencilla

¿Qué son las incrustaciones? Una guía en lenguaje sencillo sobre vectores, similitud de cosenos y búsqueda semántica, con un pequeño ejemplo que eje…

Leer artículo →
DevOps

Implementación azul-verde versus implementación canaria: diferencias, compensaciones y cómo elegir

Explicación de la implementación azul-verde versus canaria: cómo funciona cada uno, costo, riesgo y reversión, agrupación estable de usuarios que pr…

Leer artículo →
Automatización de pruebas

Pruebas inestables: qué las causa y cómo solucionarlas para siempre

Pruebas inestables explicadas con demostraciones que realizamos: las causas principales, cómo confirmar y diagnosticar una, correcciones adecuadas p…

Leer artículo →
Pruebas de software

Pruebas de carga frente a pruebas de estrés: diferencias, métricas y ejemplos de k6

Explicación de las pruebas de carga frente a las pruebas de estrés: qué prueba cada una, pruebas de picos y de absorción, las métricas que importan,…

Leer artículo →
Pruebas de software

Caso de prueba frente a escenario de prueba: diferencias clave, ejemplos y cuándo utilizar cada uno

Caso de prueba versus escenario de prueba explicado: definiciones claras, una tabla en paralelo, una función de restablecimiento de contraseña tomad…

Leer artículo →
Bases de datos y SQL

Optimización de consultas SQL: lea planes de ejecución y corrija consultas lentas, con tiempos

Optimización de consultas SQL probada en un millón de filas: lea planes de ejecución, agregue los índices correctos, corrija filtros no sargables, u…

Leer artículo →
Bases de datos y SQL

SQL UNION vs UNION ALL: diferencias, ejemplos y rendimiento probado

SQL UNION vs UNION ALL explicado con consultas que ejecutamos: duplicados, las reglas que siguen ambos, un error de datos real, rendimiento medido, …

Leer artículo →
Desarrollo de software

Tutorial de JavaScript Fetch API: GET, POST, manejo de errores y tiempos de espera

Un tutorial de JavaScript Fetch API probado en un servidor local: GET y POST, por qué 404 no arroja, un asistente reutilizable, cadenas de consulta,…

Leer artículo →
Desarrollo de software

Manejo de archivos Python: lectura, escritura, CSV, JSON y pathlib con ejemplos

El manejo de archivos Python se explica con el código que ejecutamos: modos abiertos, lectura de archivos grandes, CSV, JSON, pathlib, archivos bina…

Leer artículo →
Desarrollo de software

Clases y objetos de Python: tutorial de programación orientada a objetos con ejemplos reales

Clases y objetos de Python explicados con el código que ejecutamos: __init__, métodos, atributos de clase versus instancia, herencia, propiedades, m…

Leer artículo →
Inteligencia artificial

¿Qué es un modelo de lenguaje grande? Cómo funcionan los LLM, explicados sin exageraciones

¿Qué es un modelo de lenguaje grande? Los LLM explicados en lenguaje sencillo: tokens, incrustaciones, atención, entrenamiento, ventanas de temperat…

Leer artículo →
DevOps

Comandos de Linux para principiantes: la guía esencial de terminal con ejemplos

Comandos de Linux para principiantes, agrupados por tarea: navegación, archivos, visualización de registros, grep, canalizaciones, permisos, proceso…

Leer artículo →
Automatización de pruebas

Selenium vs Playwright: diferencias clave, comparación de códigos y cuál elegir

Comparación de Selenium vs Playwright: arquitectura, espera, soporte de navegador e idioma, depuración, la misma prueba en ambas herramientas, conse…

Leer artículo →
Pruebas de software

Partición de equivalencia: técnica de diseño de pruebas explicada con ejemplos resueltos

Explicación de la partición de equivalencia: cómo encontrar particiones válidas e inválidas, ejemplos prácticos para edades, contraseñas y cupones, …

Leer artículo →
Pruebas de software

Severidad vs Prioridad en Pruebas de Software: Diferencias, Matriz y Ejemplos Reales

Explicación de gravedad versus prioridad en las pruebas de software: definiciones claras, una matriz de cuatro vías con ejemplos, escalas de niveles…

Leer artículo →
Bases de datos y SQL

Tutorial de subconsultas SQL: tipos, subconsultas correlacionadas y EXISTENCIAS con ejemplos

Un tutorial de subconsultas SQL con consultas que ejecutamos: subconsultas escalares, IN, FROM y SELECT, subconsultas correlacionadas, EXISTS, la tr…

Leer artículo →
Bases de datos y SQL

Transacciones SQL y ACID explicados: COMMIT, ROLLBACK y niveles de aislamiento

Transacciones SQL y ACID explicadas con una transferencia bancaria que ejecutamos: COMMIT, ROLLBACK, puntos de guardado, bloqueos, niveles de aislam…

Leer artículo →
Desarrollo de software

Git merge vs rebase: diferencias, ejemplos y cuándo usar cada uno

Git merge vs rebase explicado con salida real del log, una tabla comparativa, la regla de oro del rebase y un flujo de trabajo seguro para equipos.

Leer artículo →
Desarrollo de software

List comprehension en Python: sintaxis, ejemplos y cuándo evitarla

List comprehension en Python explicada: sintaxis, filtros, if-else, bucles anidados, tiempos medidos y cuándo es mejor un bucle for normal.

Leer artículo →