SQL / DQL: Subconsultas, consultas embebidas en otras consultas.
Las subconsultas (o consultas anidadas) representan uno de los pilares más sofisticados del lenguaje SQL. Formalmente, una subconsulta es una instrucción SELECT que se encuentra embebida dentro de otra sentencia SQL principal (ya sea otro SELECT, INSERT, UPDATE o DELETE).
En el contexto de Bases de Datos Avanzadas, las subconsultas permiten resolver problemas de extracción de datos que requieren múltiples pasos lógicos en una sola ejecución. A continuación, analizaremos su implementación profesional utilizando el esquema iris.

1. Subconsultas en la cláusula SELECT (Subconsultas Escalares)
Una subconsulta en el SELECT debe ser escalar, es decir, debe devolver exactamente un solo valor (una fila y una columna). Se ejecuta una vez por cada fila procesada por la consulta externa.
Caso de uso: Comparar cada muestra individual contra el promedio global de la longitud del pétalo.
SELECT
id,
petal_length,
(SELECT ROUND(AVG(petal_length), 2) FROM iris.iris_muestras) AS promedio_global,
ROUND(petal_length - (SELECT AVG(petal_length) FROM iris.iris_muestras), 2) AS desviacion
FROM iris_muestras;
Aunque son útiles, las subconsultas en el SELECT pueden impactar el rendimiento en conjuntos de datos masivos. En entornos productivos, a menudo se prefieren las Window Functions o CTEs por eficiencia.
2. Subconsultas en la cláusula FROM (Tablas Derivadas)
Cuando una subconsulta se ubica en el FROM, el resultado se trata como una tabla temporal o virtual. En PostgreSQL, es obligatorio asignar un alias a estas tablas derivadas.
Caso de uso: Obtener el promedio de medidas por especie y unirlo con la tabla de detalles para ver el clima ideal.
SELECT
ed.nombre_especie,
stats.promedio_sepalo,
ed.clima_ideal
FROM (
-- Esta es la tabla derivada
SELECT
especie_id,
ROUND(AVG(sepal_length), 2) AS promedio_sepalo
FROM iris_muestras
GROUP BY especie_id
) AS stats
JOIN especies_detalles ed ON stats.especie_id = ed.id;
3. Subconsultas en la cláusula WHERE (Predicados de Filtrado)
Es el uso más común. Permite filtrar registros de la consulta principal basándose en los resultados de una consulta interna. Pueden ser de dos tipos:
- Independientes: Se ejecutan una sola vez.
- Correlacionadas: Hacen referencia a columnas de la consulta externa y se ejecutan fila por fila.
Caso de uso (Independiente): Encontrar todas las muestras cuyas especies viven en climas “Húmedo”.
SELECT * FROM iris_muestras
WHERE especie_id IN (
SELECT id
FROM especies_detalles
WHERE clima_ideal = 'Húmedo'
);
Caso de uso (Correlacionada): Encontrar flores que son más largas que el promedio de su propia especie.
SELECT m1.id, m1.especie_id, m1.petal_length
FROM iris_muestras m1
WHERE m1.petal_length > (
-- Esta consulta depende del valor de m1 (externo)
SELECT AVG(m2.petal_length)
FROM iris_muestras m2
WHERE m2.especie_id = m1.especie_id
);
4. Subconsultas en la cláusula HAVING (Filtros de Agregación)
El HAVING se utiliza para filtrar grupos. Una subconsulta aquí permite comparar un agregado de un grupo contra un valor calculado dinámicamente.
Caso de uso: Mostrar las especies cuyo ancho de pétalo promedio es superior al ancho de pétalo promedio de la especie ‘Setosa’.
SELECT
especie_id,
AVG(petal_width) AS promedio_especie
FROM iris_muestras
GROUP BY especie_id
HAVING AVG(petal_width) > (
-- Subconsulta que obtiene el promedio de una especie específica
SELECT AVG(m.petal_width)
FROM iris_muestras m
JOIN especies_detalles e ON m.especie_id = e.id
WHERE e.nombre_especie = 'Setosa'
);
Resumen
Para determinar qué tipo de subconsulta utilizar, se debe evaluar la estructura del resultado deseado:
| Ubicación | Tipo de resultado | Propósito principal |
| SELECT | Escalar | Atributos calculados comparativos por fila. |
| FROM | Conjunto de datos (Tabla) | Pre-procesamiento o agregación de datos antes del Join. |
| WHERE | Lista o valor único | Restricción basada en condiciones externas. |
| HAVING | Escalar (Agregado) | Restricción de grupos basada en comparaciones métricas. |
Consideración de Rendimiento: Subconsultas vs. CTE
En PostgreSQL, para consultas de alta complejidad, se recomienda evaluar si una CTE (Common Table Expression) es más legible y eficiente que múltiples subconsultas anidadas, especialmente cuando el mismo conjunto de datos debe ser referenciado más de una vez.