0Pricing
Coding Interview Prep · Lección

EXISTS y NOT EXISTS correlacionados

Conozca la alternativa robusta al anti-join que gestiona correctamente los valores NULL

EXISTS y NOT EXISTS correlacionados es una lección gratuita de Coding Interview Prep en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Coding Interview Prep, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Coding Interview Prep incluye 4 lecciones en total.

EXISTS comprueba la existencia

EXISTS recibe una subconsulta y devuelve TRUE en cuanto esa subconsulta produce al menos una fila; de lo contrario, devuelve FALSE. Nunca devuelve las filas en sí.

Con una subconsulta correlacionada en su interior, EXISTS se convierte en una comprobación de existencia para cada fila externa: "¿existe una fila coincidente para esta fila externa?"

Como se detiene al encontrar la primera coincidencia, no importa cuántas filas coincidan. Este detalle semántico es un tema frecuente en las entrevistas.

Un EXISTS correlacionado básico

Encuentre los clientes que hayan realizado al menos un pedido. La consulta interna está correlacionada mediante o.customer_id = c.customer_id.

Para cada cliente, EXISTS pregunta: ¿hay algún pedido de este cliente? Si lo hay, conserve el cliente.

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

Por qué se usa SELECT 1 dentro de EXISTS

Dentro de EXISTS verá SELECT 1, SELECT * o SELECT NULL. Todos son equivalentes.

EXISTS solo comprueba si se devuelven filas, nunca su contenido, por lo que las columnas proyectadas son irrelevantes. El optimizador las ignora.

SELECT 1 es una convención habitual que indica la intención: "solo me interesa la existencia". Elija una opción y sea coherente; no permita que el entrevistador piense que la lista de columnas es importante aquí.

NOT EXISTS encuentra lo que falta

NOT EXISTS invierte la comprobación: conserva la fila externa únicamente cuando la subconsulta correlacionada no devuelve ninguna fila.

Esta es la antiunión canónica: clientes sin pedidos, productos que nunca se han vendido y estudiantes sin entregas.

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

La trampa de NULL con NOT IN

Este es un punto clave en las entrevistas. NOT IN frente a una subconsulta que puede contener NULL se comporta de forma peligrosa: si la lista contiene aunque sea un NULL, NOT IN no devuelve ninguna fila.

Esto ocurre porque comparar con NULL produce UNKNOWN, y NOT IN requiere que cada comparación sea falsa. Un solo UNKNOWN invalida toda la condición.

NOT EXISTS no tiene este problema; simplemente comprueba la existencia de filas y gestiona los NULL de forma segura.

-- Risky: returns nothing if any o.customer_id is NULL
SELECT c.customer_id FROM customers c
WHERE c.customer_id NOT IN (SELECT o.customer_id FROM orders o);

-- Safe: NULLs do not break it
SELECT c.customer_id FROM customers c
WHERE NOT EXISTS (
    SELECT 1 FROM orders o WHERE o.customer_id = c.customer_id
);

Por qué NOT EXISTS es seguro con NULL

La razón está en la lógica de coincidencia. NOT EXISTS comprueba si alguna fila interna satisface o.customer_id = c.customer_id.

Una fila cuyo o.customer_id sea NULL nunca satisface esa igualdad (NULL = cualquier valor produce UNKNOWN, no TRUE), por lo que simplemente no cuenta como coincidencia. La comprobación de existencia sigue siendo correcta.

Con NOT IN, ese mismo NULL pasa a formar parte de una comparación de listas cuyo resultado UNKNOWN elimina toda la salida. Por eso, en las entrevistas para puestos sénior se suele preferir NOT EXISTS.

EXISTS con condiciones adicionales

La subconsulta correlacionada puede incluir más predicados. Encuentre clientes que hayan realizado al menos un pedido superior a 1000.

La condición adicional se encuentra dentro de la subconsulta EXISTS y se evalúa para cada cliente.

SELECT c.customer_id, c.name
FROM customers c
WHERE EXISTS (
    SELECT 1
    FROM orders o
    WHERE o.customer_id = c.customer_id
      AND o.amount > 1000
);

Rendimiento: comportamiento de cortocircuito

EXISTS puede dejar de explorar la relación interna en cuanto encuentra una fila coincidente. No construye ni cuenta un conjunto de resultados completo.

Por eso, EXISTS suele ser eficiente, especialmente cuando la columna correlacionada está indexada, porque cada búsqueda por fila puede encontrar rápidamente una coincidencia y detenerse.

En cambio, un COUNT(*) > 0 correlacionado obliga a contar todas las coincidencias. Prefiera EXISTS cuando solo necesite una respuesta de sí o no.

EXISTS frente a COUNT para comprobar existencia

A veces, los candidatos escriben un recuento correlacionado para comprobar si existe una coincidencia. Funciona, pero desperdicia trabajo.

La versión con COUNT contabiliza todos los pedidos coincidentes; EXISTS termina después del primero. Para una comprobación de existencia pura, EXISTS comunica mejor la intención y permite que el optimizador aplique un cortocircuito.

-- Works but counts everything
SELECT c.customer_id FROM customers c
WHERE (SELECT COUNT(*) FROM orders o
       WHERE o.customer_id = c.customer_id) > 0;

-- Better: stops at first match
SELECT c.customer_id FROM customers c
WHERE EXISTS (SELECT 1 FROM orders o
              WHERE o.customer_id = c.customer_id);

Ejemplo práctico: productos que nunca se han pedido

Una consigna clásica de entrevista sobre anti-join: enumerar los productos que nunca se han pedido. NOT EXISTS se lee casi como el requisito en inglés.

Para cada producto, compruebe si alguna línea de pedido hace referencia a él; conserve solo aquellos para los que no haya ninguna.

SELECT p.product_id, p.name
FROM products p
WHERE NOT EXISTS (
    SELECT 1
    FROM order_items oi
    WHERE oi.product_id = p.product_id
);

EXISTS dentro de NOT EXISTS para consultas de tipo división

Anidar EXISTS dentro de NOT EXISTS expresa una división relacional: «encuentre filas que coincidan con TODO un conjunto». Una consigna clásica es «clientes que hayan pedido todos los productos de una categoría».

La lógica es la siguiente: conserve un cliente cuando no exista ningún producto que no haya pedido. Ese doble negativo es característico de una consulta de división, y los entrevistadores lo utilizan para comprobar un dominio profundo de EXISTS.

SELECT c.customer_id
FROM customers c
WHERE NOT EXISTS (
    SELECT 1 FROM products p
    WHERE p.category = 'Coffee'
      AND NOT EXISTS (
          SELECT 1 FROM order_items oi
          JOIN orders o ON o.order_id = oi.order_id
          WHERE oi.product_id = p.product_id
            AND o.customer_id = c.customer_id
      )
);

Comprobación rápida

Elija la forma más segura de encontrar clientes sin pedidos.

Repaso: EXISTS y NOT EXISTS correlacionados

Conclusiones clave:

  • EXISTS comprueba la existencia por cada fila y aplica un cortocircuito al encontrar la primera coincidencia; la columna elegida dentro de ella es irrelevante (use SELECT 1).
  • NOT EXISTS es el anti-join seguro frente a NULL para encontrar filas sin coincidencias.
  • NOT IN con un NULL en la lista no devuelve nada; prefiera NOT EXISTS.
  • Para comprobar existencia, EXISTS es mejor que un COUNT(*) > 0 correlacionado porque se detiene antes.

Mencione espontáneamente la trampa de los NULL con NOT IN; es una señal fiable de madurez en SQL.

Preguntas frecuentes

¿La lección «EXISTS y NOT EXISTS correlacionados» es gratis?

Sí — el texto completo de «EXISTS y NOT EXISTS correlacionados» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Coding Interview Prep, actualiza a CoddyKit PRO. El curso de Coding Interview Prep incluye 4 lecciones en total.

¿Qué aprenderé en «EXISTS y NOT EXISTS correlacionados»?

Conozca la alternativa robusta al anti-join que gestiona correctamente los valores NULL Practicas Coding Interview Prep con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Coding Interview Prep?

No se requiere experiencia previa. Coding Interview Prep en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.

¿Cuánto tiempo toma la lección «EXISTS y NOT EXISTS correlacionados»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Coding Interview Prep?

Sí. Cada lección de Coding Interview Prep incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Anatomía de una subconsulta correlacionada
  2. Agregaciones por grupo sin GROUP BY
  3. EXISTS y NOT EXISTS correlacionados
  4. Reescribir subconsultas correlacionadas como joins
← Volver a Coding Interview Prep