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 (useSELECT 1).NOT EXISTSé a antijunção segura contra NULL para encontrar linhas sem correspondência.NOT INcom um NULL na lista não retorna nada; prefiraNOT EXISTS.- Para verificar existência, EXISTS é melhor que uma
COUNT(*) > 0correlacionada 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
- Anatomia de uma subconsulta correlacionada
- Agregações por grupo sem GROUP BY
- EXISTS e NOT EXISTS correlacionados
- Reescrevendo subconsultas correlacionadas como junções