0Pricing
SQL Interview Prep · Aula

A armadilha de WHERE em junções externas

Entenda por que filtrar uma coluna de uma junção externa em WHERE a transforma silenciosamente em uma junção interna.

A armadilha de WHERE em junções externas é uma aula grátis de SQL Interview Prep no CoddyKit. Esta é a aula 4 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 armadilha que engana todos

Este é o erro mais comum em junções externas que os entrevistadores inserem de propósito: "Mostre todos os clientes e seus pedidos de 2024, incluindo os clientes sem pedidos de 2024."

O candidato escreve um LEFT JOIN e depois adiciona um filtro de data em WHERE; assim, os clientes sem pedidos de 2024 desaparecem silenciosamente. O LEFT JOIN se degrada discretamente para um INNER JOIN. Entender o motivo é um sinal de experiência sênior.

A consulta com erro

Este é o erro. A consulta parece razoável: manter todos os clientes, juntar seus pedidos e filtrar para 2024.

Mas os clientes sem pedidos, ou sem pedidos de 2024, desaparecem do resultado. O requisito de incluí-los não é atendido.

-- BUG: drops customers with no 2024 order
SELECT c.name, o.id, o.order_date
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.order_date >= '2024-01-01';

Por que isso falha

Relembre a ordem de execução: o JOIN acontece primeiro, produzindo linhas nas quais os clientes sem correspondência têm NULL em todas as colunas do pedido. Depois, WHERE é executado.

Para um cliente sem correspondência, o.order_date é NULL, portanto o.order_date >= '2024-01-01' é avaliado como UNKNOWN, não como verdadeiro. WHERE mantém apenas as linhas cujo resultado é verdadeiro, então as linhas com NULL são filtradas, exatamente aquelas que o LEFT JOIN se esforçou para preservar.

NULL derrota o filtro

Qualquer comparação com NULL produz UNKNOWN: NULL >= '2024-01-01' resulta em UNKNOWN, NULL = 5 resulta em UNKNOWN e até NULL <> 5 resulta em UNKNOWN.

Como WHERE mantém apenas as linhas avaliadas como TRUE, todas as linhas preservadas sem correspondência são descartadas. O objetivo da junção externa é completamente anulado por um único predicado WHERE em uma coluna da tabela da direita.

A correção: filtrar em ON

Mova o filtro para a cláusula ON. Ali, ele se torna parte da condição de correspondência e é aplicado antes da preservação das linhas, portanto os clientes sem correspondência continuam presentes com NULL.

-- CORRECT: filter lives in ON
SELECT c.name, o.id, o.order_date
FROM customers c
LEFT JOIN orders o
  ON o.customer_id = c.id
  AND o.order_date >= '2024-01-01';
-- customers with no 2024 order: kept, NULL order

ON vs WHERE em uma frase

A regra para recitar em uma entrevista é:

Para a tabela preservada (externa), as condições referentes à outra tabela devem ficar em ON; as condições referentes à própria tabela preservada devem ficar em WHERE.

  • ON decide o que conta como correspondência (é executado durante a junção).
  • WHERE filtra as linhas finais (é executado depois e remove as linhas com NULL).

Resultados lado a lado

Os mesmos dados, duas posições, respostas diferentes. Suponha que Carol não tenha um pedido de 2024.

  • Filtro em WHERE: Carol desaparece. Na prática, é uma junção interna.
  • Filtro em ON: Carol aparece uma vez com NULL nas colunas do pedido; o requisito é atendido.

A diferença na saída é justamente o objetivo da armadilha.

-- ON version output
-- Alice | 50 | 2024-03-01
-- Bob   | 20 | 2024-05-02
-- Carol | NULL | NULL   <-- preserved

Quando WHERE está correto

Nem todo uso de WHERE em uma junção externa é um erro. Filtrar a tabela preservada é correto, pois isso não envolve NULL provenientes da junção.

E a junção de exclusão da lição anterior usa WHERE o.id IS NULL intencionalmente para aproveitar exatamente esse comportamento. A habilidade está em saber em qual caso você se encontra.

-- Fine: filtering the preserved (left) table
SELECT c.name, o.id
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE c.country = 'US';

A heurística de detecção

Ao revisar uma junção externa, examine a cláusula WHERE em busca de predicados na tabela não preservada (exceto nos testes IS NULL da junção de exclusão).

Se você encontrar o.someColumn = ... ou um teste de intervalo ou igualdade no lado externo em WHERE, suspeite da armadilha. Pergunte: "Isso transforma meu LEFT JOIN em um INNER JOIN?" Geralmente, sim.

Várias condições

Você pode combinar as duas posições. As condições de correspondência na tabela da direita ficam em ON; um filtro genuíno aplicado depois da junção na tabela da esquerda fica em WHERE. Elas coexistem sem problemas.

SELECT c.name, o.id, o.amount
FROM customers c
LEFT JOIN orders o
  ON o.customer_id = c.id
  AND o.amount > 100          -- match condition
WHERE c.signup_year = 2023;    -- preserved-table filter

Explicando em voz alta

Na entrevista, descreva o mecanismo, não apenas a correção:

"A junção é executada primeiro e preenche as colunas da direita sem correspondência com NULL. Um predicado WHERE nessas colunas é avaliado como UNKNOWN para as linhas com NULL, e WHERE descarta as linhas que não resultam em TRUE; assim, a junção externa se transforma em uma junção interna. Colocar o predicado em ON mantém-no como condição de correspondência e preserva as linhas sem correspondência." Essa explicação funciona sempre.

Verificação rápida

Você precisa listar todos os clientes e apenas os pedidos de 2024 de cada um, mantendo os clientes que não tiveram nenhum pedido.

Recapitulação

Filtrar a coluna de uma tabela não preservada em WHERE transforma silenciosamente uma junção externa em uma junção interna, porque os valores NULL das linhas sem correspondência não satisfazem o predicado (resultam em UNKNOWN), e WHERE os descarta.

  • As condições de correspondência na tabela externa ficam em ON.
  • Os filtros na tabela preservada ficam em WHERE.
  • IS NULL em WHERE é a junção de exclusão intencional, não a armadilha.
  • Explique a ordem de execução para demonstrar que você entende o assunto.

Perguntas Frequentes

A aula “A armadilha de WHERE em junções externas” é grátis?

Sim — o texto completo de “A armadilha de WHERE em junções externas” é 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 “A armadilha de WHERE em junções externas”?

Entenda por que filtrar uma coluna de uma junção externa em WHERE a transforma silenciosamente em uma junção interna. 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 4 de 4.

Quanto tempo leva a aula “A armadilha de WHERE em junções externas”?

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. LEFT JOIN e preservação de linhas sem correspondência
  2. Semântica de RIGHT e FULL OUTER JOIN
  3. Encontrando linhas sem correspondência (anti-junção)
  4. A armadilha de WHERE em junções externas
← Voltar para SQL Interview Prep