Encontrando linhas sem correspondência (anti-junção)
Use o padrão LEFT JOIN / IS NULL para encontrar registros órfãos e dados ausentes.
Encontrando linhas sem correspondência (anti-junção) é 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.
A questão da junção de exclusão
Uma das perguntas mais frequentes sobre junções externas é: "Encontre os clientes que nunca fizeram um pedido." Ou: "Liste os produtos que nunca foram vendidos" ou "os pedidos sem um cliente correspondente".
Todas têm o mesmo formato: linhas de uma tabela sem correspondência em outra. O padrão mais claro é a junção de exclusão, construída com um LEFT JOIN seguido de um filtro IS NULL.
A ideia central
Comece com um LEFT JOIN: ele mantém todas as linhas da esquerda, e as linhas da esquerda sem correspondência recebem NULL nas colunas da tabela da direita.
Assim, as linhas sem correspondência são exatamente aquelas em que uma coluna da tabela da direita é NULL. Filtre por essa condição para isolar as linhas sem correspondência. Esse é todo o truque.
Construindo o padrão
Este é o padrão clássico de junção de exclusão para encontrar clientes sem pedidos. Leia-o em duas etapas: LEFT JOIN mantém todos os clientes; depois, WHERE o.customer_id IS NULL mantém apenas os que não têm correspondência.
SELECT c.id, c.name
FROM customers c
LEFT JOIN orders o
ON o.customer_id = c.id
WHERE o.customer_id IS NULL;
-- only customers with zero ordersPor que isso funciona, passo a passo
Acompanhe o processo com nossos dados, nos quais Carol não tem pedidos:
- LEFT JOIN produz Alice (x2), Bob (x1) e Carol com NULL nas colunas da direita.
WHERE o.customer_id IS NULLdescarta Alice e Bob (as colunas da direita deles têm valores reais).- Apenas a linha de Carol, aquela com NULL criado pela junção, permanece.
O filtro é executado depois da junção, portanto vê esses valores NULL e seleciona precisamente as linhas sem correspondência.
Escolha a coluna certa para verificar
Verifique uma coluna da tabela da direita que nunca possa legitimamente ser NULL em uma correspondência real, de preferência a chave da junção ou a chave primária.
Se você verificar uma coluna que aceite NULL, como o.shipped_at, também encontrará pedidos que existem, mas ainda não foram enviados, o que seria uma resposta incorreta. Verificar o.customer_id (a chave da junção) ou o.id (a chave primária) garante que NULL signifique "nenhuma linha correspondente".
-- SAFE: join key / primary key
WHERE o.id IS NULL
-- RISKY: a nullable data column
WHERE o.shipped_at IS NULL -- catches unshipped too!Junção de exclusão vs NOT IN
Os entrevistadores comparam a junção de exclusão com NOT IN. Elas parecem equivalentes, mas diferem quando há valores NULL.
Se a subconsulta retornar qualquer NULL, NOT IN não retornará nenhuma linha, um conhecido erro silencioso. A junção de exclusão com LEFT JOIN / IS NULL não é afetada por esse problema.
-- DANGEROUS if any customer_id is NULL
SELECT id, name FROM customers
WHERE id NOT IN (SELECT customer_id FROM orders);
-- SAFE anti-join, same intent
SELECT c.id, c.name FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.id IS NULL;Junção de exclusão vs NOT EXISTS
A outra alternativa equivalente é NOT EXISTS com uma subconsulta correlacionada. Ela também trata NULL corretamente e costuma ser igualmente rápida.
As três opções (LEFT JOIN/IS NULL, NOT EXISTS e NOT IN) podem expressar junções de exclusão, mas em uma entrevista prefira LEFT JOIN/IS NULL ou NOT EXISTS por serem seguras com NULL. Mencionar a armadilha de NOT IN garante pontos.
SELECT c.id, c.name
FROM customers c
WHERE NOT EXISTS (
SELECT 1 FROM orders o
WHERE o.customer_id = c.id
);Um erro comum
Um erro frequente é colocar a condição de ausência de correspondência na cláusula ON em vez de WHERE.
Escrever ... ON o.customer_id = c.id AND o.id IS NULL não filtra o resultado; apenas altera o que conta como correspondência, e todos os clientes continuam sendo preservados pelo LEFT JOIN. A condição IS NULL precisa ficar em WHERE, aplicada depois da junção. Abordaremos essa armadilha em detalhes na próxima lição.
Encontrando linhas filhas sem correspondência
O padrão também funciona na outra direção. Para encontrar pedidos que fazem referência a um cliente ausente (linhas órfãs, uma verificação de integridade dos dados), preserve orders e verifique se o lado do cliente é NULL.
SELECT o.id AS order_id, o.customer_id
FROM orders o
LEFT JOIN customers c
ON c.id = o.customer_id
WHERE c.id IS NULL;
-- orders pointing to a non-existent customerContando as linhas órfãs
Muitas vezes, a solicitação é apenas uma contagem: "Quantos clientes nunca fizeram um pedido?" Envolva a junção de exclusão em outra consulta ou faça a contagem diretamente.
Como a junção de exclusão já retorna uma linha por linha órfã, um simples COUNT(*) é correto neste caso: há exatamente uma linha para cada cliente sem correspondência.
SELECT COUNT(*) AS never_ordered
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.id IS NULL;O modelo reutilizável
Memorize este esqueleto de três linhas; ele resolve uma grande variedade de perguntas de entrevista:
FROM keep_table kLEFT JOIN other o ON o.fk = k.idWHERE o.id IS NULL
Troque as tabelas e as chaves para encontrar produtos não vendidos, chamados não atribuídos, usuários sem acessos e qualquer situação descrita como "X sem um Y correspondente".
Verificação rápida
Você precisa dos produtos que nunca apareceram em order_items.
Recapitulação
A junção de exclusão encontra linhas sem correspondência: LEFT JOIN seguido de WHERE right_key IS NULL.
- Verifique a chave da junção ou a chave primária, nunca uma coluna de dados que aceite NULL.
- A condição
IS NULLdeve ficar emWHERE, não emON. - É equivalente a
NOT EXISTS; prefira-o aNOT IN, que falha quando há NULL. - Inverta as tabelas para encontrar linhas filhas órfãs.
Um modelo, muitas perguntas: "X sem um Y correspondente".
Perguntas Frequentes
A aula “Encontrando linhas sem correspondência (anti-junção)” é grátis?
Sim — o texto completo de “Encontrando linhas sem correspondência (anti-junção)” é 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 “Encontrando linhas sem correspondência (anti-junção)”?
Use o padrão LEFT JOIN / IS NULL para encontrar registros órfãos e dados ausentes. 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 “Encontrando linhas sem correspondência (anti-junção)”?
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
- LEFT JOIN e preservação de linhas sem correspondência
- Semântica de RIGHT e FULL OUTER JOIN
- Encontrando linhas sem correspondência (anti-junção)
- A armadilha de WHERE em junções externas