0Pricing
SQL Interview Prep · Aula

EXISTS e NOT EXISTS correlacionados

Conheça a alternativa robusta de anti-junção que trata NULLs corretamente.

EXISTS e NOT EXISTS correlacionados é uma aula grátis de SQL Interview Prep no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de SQL Interview Prep, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de SQL Interview Prep inclui 4 aulas no total.

EXISTS verifica a presença

EXISTS recebe uma subconsulta e retorna TRUE assim que essa subconsulta produz pelo menos uma linha; caso contrário, retorna FALSE. Ele nunca retorna as próprias linhas.

Com uma subconsulta correlacionada no interior, EXISTS se torna um teste de presença por linha externa: "existe uma linha correspondente para esta linha externa?"

Como para na primeira correspondência, não importa quantas linhas correspondam. Esse detalhe semântico é um dos pontos favoritos em entrevistas.

Uma EXISTS correlacionada básica

Encontre os clientes que fizeram pelo menos um pedido. A consulta interna é correlacionada por meio de o.customer_id = c.customer_id.

Para cada cliente, EXISTS pergunta: existe algum pedido para este cliente? Se sim, mantenha o 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 que usar SELECT 1 dentro de EXISTS

Você verá SELECT 1, SELECT * ou SELECT NULL dentro de EXISTS. Todos são equivalentes.

EXISTS verifica apenas se alguma linha é retornada, nunca seu conteúdo, portanto as colunas projetadas são irrelevantes. O otimizador as ignora.

SELECT 1 é uma convenção comum que sinaliza a intenção: "Só me importa a existência." Escolha uma opção e seja consistente; não permita que um entrevistador pense que a lista de colunas é relevante aqui.

NOT EXISTS encontra o que falta

NOT EXISTS inverte o teste: mantenha a linha externa apenas quando a subconsulta correlacionada não retornar nenhuma linha.

Esta é a antijunção canônica: clientes sem pedidos, produtos nunca vendidos, estudantes sem envios.

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

A armadilha de NULL com NOT IN

Este é um ponto crucial para entrevistas. NOT IN aplicado a uma subconsulta que pode conter NULL comporta-se de forma traiçoeira: se a lista tiver ao menos um NULL, NOT IN não retornará linha alguma.

Isso ocorre porque comparar com NULL produz UNKNOWN, e NOT IN exige que toda comparação seja falsa. Um UNKNOWN contamina a condição inteira.

NOT EXISTS não sofre desse problema; ele simplesmente verifica a presença de linhas e lida com NULLs com segurança.

-- 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 que NOT EXISTS é seguro com NULL

O motivo está na lógica de correspondência. NOT EXISTS verifica se alguma linha interna satisfaz o.customer_id = c.customer_id.

Uma linha em que o.customer_id é NULL nunca satisfaz essa igualdade (NULL = qualquer valor resulta em UNKNOWN, não em TRUE), portanto simplesmente não conta como correspondência. O teste de presença continua correto.

Com NOT IN, esse mesmo NULL passa a fazer parte de uma comparação com uma lista cujo resultado UNKNOWN elimina toda a saída. É por isso que entrevistas para níveis seniores preferem NOT EXISTS.

EXISTS com condições adicionais

A subconsulta correlacionada pode conter mais predicados. Encontre clientes que fizeram pelo menos um pedido acima de 1000.

A condição adicional fica dentro da subconsulta EXISTS, com escopo por 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
);

Desempenho: comportamento de curto-circuito

EXISTS pode parar de varrer a relação interna assim que uma linha correspondente é encontrada. Ele não cria nem contabiliza um conjunto de resultados completo.

Isso normalmente torna EXISTS eficiente, especialmente quando a coluna correlacionada está indexada, pois cada busca por linha pode encontrar uma correspondência rapidamente e ser encerrada.

Compare com uma COUNT(*) > 0 correlacionada, que força a contabilização de todas as correspondências. Prefira EXISTS quando precisar apenas de uma resposta sim/não.

EXISTS versus COUNT para verificar presença

Às vezes, candidatos escrevem uma contagem correlacionada para testar a presença. Funciona, mas desperdiça esforço.

A versão com COUNT contabiliza todos os pedidos correspondentes; EXISTS para depois do primeiro. Para um teste puro de existência, EXISTS comunica a intenção e permite que o otimizador faça um curto-circuito.

-- 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);

Exemplo prático: produtos nunca pedidos

Uma questão clássica de entrevista sobre antijunção: liste os produtos que nunca foram pedidos. NOT EXISTS se aproxima bastante da forma como o requisito seria escrito em inglês.

Para cada produto, verifique se alguma linha de pedido faz referência a ele; mantenha apenas aqueles sem nenhuma correspondência.

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 em NOT EXISTS para consultas no estilo de divisão

Aninhar EXISTS dentro de NOT EXISTS expressa uma divisão relacional: "encontre as linhas que correspondam a ALL (todos os elementos de um conjunto)." Uma questão clássica é "clientes que pediram todos os produtos de uma categoria".

A lógica é: mantenha um cliente quando não houver nenhum produto que ele não tenha pedido. Essa dupla negação é a marca registrada de uma consulta de divisão, e os entrevistadores a usam para testar o domínio 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
      )
);

Verificação rápida

Escolha a maneira mais segura de encontrar clientes sem pedidos.

Recapitulação: EXISTS e NOT EXISTS correlacionados

Principais conclusões:

  • EXISTS é um teste de presença por linha que faz um curto-circuito na primeira correspondência; a escolha da coluna dentro dele é irrelevante (use SELECT 1).
  • NOT EXISTS é a antijunção segura contra NULL para encontrar linhas sem correspondência.
  • NOT IN com um NULL na lista não retorna nada; prefira NOT EXISTS.
  • Para verificar existência, EXISTS é melhor que uma COUNT(*) > 0 correlacionada porque para mais cedo.

Mencione espontaneamente a armadilha de NULL com NOT IN; ela é um sinal confiável de maturidade em SQL.

Perguntas Frequentes

A aula “EXISTS e NOT EXISTS correlacionados” é grátis?

Sim — o texto completo de “EXISTS e NOT EXISTS correlacionados” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de SQL Interview Prep, atualize para CoddyKit PRO. O curso de SQL Interview Prep inclui 4 aulas no total.

O que vou aprender em “EXISTS e NOT EXISTS correlacionados”?

Conheça a alternativa robusta de anti-junção que trata NULLs corretamente. Você pratica SQL Interview Prep com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar SQL Interview Prep?

Nenhuma experiência prévia é necessária. SQL Interview Prep no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.

Quanto tempo leva a aula “EXISTS e NOT EXISTS correlacionados”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de SQL Interview Prep?

Sim. Cada aula de SQL Interview Prep inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Anatomia de uma subconsulta correlacionada
  2. Agregações por grupo sem GROUP BY
  3. EXISTS e NOT EXISTS correlacionados
  4. Reescrevendo subconsultas correlacionadas como junções
← Voltar para SQL Interview Prep