Subconsultas, EXISTS y NOT EXISTS: utilizar resultados relacionados

Una consulta puede necesitar la respuesta de otra: saber si un cliente tiene pedidos, comparar un precio con el promedio o recuperar un valor calculado para la fila actual.

Una subconsulta es una consulta escrita dentro de otra instrucción. EXISTS y NOT EXISTS se especializan en responder si la consulta interna encuentra al menos una fila.

La idea

La subconsulta puede devolver:

  • un solo valor, utilizado dentro de una expresión;
  • una lista, utilizada por operadores como IN;
  • un conjunto cuya mera existencia se comprueba con EXISTS.

Una subconsulta correlacionada utiliza columnas de la consulta exterior y se evalúa lógicamente para cada fila de ese conjunto. La correlación es precisamente esa referencia desde la consulta interna hacia la fila exterior actual.

EXISTS: comprobar presencia

EXISTS devuelve verdadero cuando la subconsulta encuentra al menos una fila. Las columnas seleccionadas dentro no cambian esa respuesta.

WHERE EXISTS
(
    Subconsulta
)

Queremos obtener los clientes que tienen al menos un pedido:

SELECT
    c.IdCliente,
    c.Nombre
FROM dbo.Cliente AS c
WHERE EXISTS
(
    SELECT 1
    FROM dbo.Pedido AS p
    WHERE p.IdCliente = c.IdCliente
)
ORDER BY c.Nombre;

EXISTS no necesita devolver columnas concretas. SELECT 1 expresa que solo nos interesa comprobar si existe alguna fila relacionada.

NOT EXISTS: comprobar ausencia

NOT EXISTS devuelve verdadero cuando la subconsulta no encuentra filas. Conserva la fila exterior únicamente cuando no existe una coincidencia interna.

WHERE NOT EXISTS
(
    Subconsulta
)

Para encontrar clientes sin pedidos:

SELECT
    c.IdCliente,
    c.Nombre
FROM dbo.Cliente AS c
WHERE NOT EXISTS
(
    SELECT 1
    FROM dbo.Pedido AS p
    WHERE p.IdCliente = c.IdCliente
)
ORDER BY c.Nombre;
IdCliente Nombre
3 Carla Ruiz

NOT EXISTS suele expresar con claridad una búsqueda de ausencias y no tiene el problema que puede aparecer con NOT IN cuando la lista interna contiene NULL.

Utilizar una subconsulta escalar

Una subconsulta que devuelve exactamente un valor se denomina escalar y puede formar parte de una expresión:

Expresion >
(
    SubconsultaEscalar
)

AVG(Precio) calcula el promedio de los precios que llegan a la subconsulta. Como una agregación sin GROUP BY devuelve una sola fila, ese promedio puede compararse con el precio de cada producto exterior.

SELECT
    p.IdProducto,
    p.Nombre,
    p.Precio
FROM dbo.Producto AS p
WHERE p.Precio >
(
    SELECT AVG(Precio)
    FROM dbo.Producto
    WHERE Activo = 1
);

Si la subconsulta escalar devuelve más de una fila, SQL Server genera un error.

Subconsulta o JOIN

No existe una sustitución automática. EXISTS comunica una prueba de existencia y no multiplica las filas exteriores por cada coincidencia interna. Un JOIN resulta apropiado cuando necesitamos columnas de ambos lados, pero puede duplicar una fila exterior cuando existen varias relaciones.

El optimizador es el componente de SQL Server que compara estrategias para ejecutar una consulta. Puede transformar expresiones diferentes en planes de ejecución similares; un plan describe la estrategia finalmente elegida. Elegimos primero la forma que represente correctamente la intención y después medimos si el rendimiento requiere atención.

Qué conviene comprobar

En una subconsulta correlacionada debemos identificar claramente qué columna pertenece al conjunto exterior. Un alias es un nombre corto asignado a una tabla o expresión. Ayuda a evitar referencias ambiguas y errores donde una condición termina comparando una columna consigo misma.

También revisamos la nulabilidad —si una columna admite NULL— cuando utilizamos IN y NOT IN, así como la cardinalidad, la cantidad de filas devueltas, cuando esperamos un solo valor.

Relacionado con