EXISTS responde a una pregunta de sí o no: ¿esta subconsulta devuelve alguna fila? Se usa en el WHERE para quedarse con las filas que tienen (o no tienen) algo relacionado en otra tabla: clientes con pedidos, productos sin ventas, usuarios sin actividad…

Sintaxis
SELECT columnas
FROM tabla1 t1
WHERE [NOT] EXISTS (
    SELECT 1
    FROM tabla2 t2
    WHERE t2.columna = t1.columna
);

Lo que devuelva el SELECT de dentro da igual: EXISTS solo mira si hay filas. Por convención se escribe SELECT 1.

Clientes con al menos un pedido

La subconsulta está correlacionada: usa C.idClientes, de la consulta exterior, así que se evalúa para cada cliente.

PostgreSQL en tu navegador · Ctrl+Enter para ejecutar · los cambios se deshacen al terminar
idClientes nombre apellidos
1 Fernando García Rodriguez
2 María Lopez ruiz
3 Ana Fernandez Montero
4 Luis Sanchez García
5 Alejandro Valero Martinez

Lo mismo se podría hacer con un JOIN, pero María y Luis saldrían dos veces, una por pedido, y habría que añadir DISTINCT. EXISTS devuelve cada cliente una sola vez.

Clientes sin pedidos: NOT EXISTS

PostgreSQL en tu navegador · Ctrl+Enter para ejecutar · los cambios se deshacen al terminar
idClientes nombre apellidos
6 Paloma Sanz Valdivia
7 Ignacio Herrero Dominguez

La trampa de NOT IN con NULL

Parece que esta consulta debería devolver lo mismo que la anterior:

PostgreSQL en tu navegador · Ctrl+Enter para ejecutar · los cambios se deshacen al terminar

Ejecútala: no devuelve ninguna fila. El motivo es el pedido del Horno Balay, que tiene idClientes a NULL. Para SQL, 6 NOT IN (3, 2, 2, 1, 4, 4, 5, NULL) significa “6 es distinto de 3 y de 2 y … y de NULL”, y comparar con NULL nunca es verdadero. Basta un solo NULL en la subconsulta para que NOT IN no devuelva nada.

NOT EXISTS no tiene ese problema, porque la condición P.idClientes = C.idClientes simplemente no se cumple para el pedido sin cliente.

Si usas NOT IN con una subconsulta, filtra los nulos: NOT IN (SELECT idClientes FROM Pedidos WHERE idClientes IS NOT NULL). O mejor, usa NOT EXISTS.

EXISTS con más condiciones

La subconsulta puede llevar cualquier filtro. Clientes que han comprado alguna consola:

PostgreSQL en tu navegador · Ctrl+Enter para ejecutar · los cambios se deshacen al terminar
nombre apellidos
Alejandro Valero Martinez
María Lopez ruiz

EXISTS, IN o JOIN

Necesitas… Usa
Filtrar filas que tienen algo relacionado EXISTS o IN (con datos sin NULL, el resultado es el mismo)
Filtrar filas que no tienen nada relacionado NOT EXISTS
Mostrar columnas de las dos tablas JOIN
Comparar con una lista fija de valores IN ('a', 'b', 'c')

En SQL Server el optimizador suele convertir EXISTS e IN en el mismo plan de ejecución, así que la elección tiene más que ver con la claridad y con el comportamiento ante NULL que con la velocidad.

Practica

  1. Lista los productos cuyo cliente tiene cuenta registrada (cuenta IS NOT NULL).
  2. Encuentra los clientes que no han hecho ningún pedido después del 1 de agosto de 2022.
  3. Arregla la consulta de NOT IN para que devuelva a Paloma e Ignacio.