SQLJOINLEFT JOINtutorial

O que é LEFT JOIN no SQL? Um guia para iniciantes

LEFT JOIN mantém todas as linhas da tabela esquerda; as correspondências ausentes à direita viram NULL. Cobrimos a sintaxe, a diferença em relação ao INNER JOIN, a busca de órfãos e três exercícios.

7 min de leituraSQL · JOIN · LEFT JOIN · tutorial · beginner

LEFT JOIN (nome completo LEFT OUTER JOIN) é uma junção em que todas as linhas da tabela esquerda acabam no resultado. Quando não há correspondência à direita, as colunas do lado direito ficam NULL.

Compare com o INNER JOIN: aquele descarta as linhas sem correspondência. LEFT JOIN as mantém, apenas marca "nada à direita".

Analogia. Uma professora distribui provas. Nem todo mundo entregou a sua.

  • INNER JOIN — "me mostre apenas os alunos que entregaram uma prova, com a nota deles".
  • LEFT JOIN — "me mostre todos os alunos; a nota se entregaram, em branco se não".

A segunda é mais frequentemente o que você precisa na vida real — você quer ver quem está ficando para trás.

Por que LEFT JOIN importa

Cenários clássicos:

  1. Uma lista mais informação opcional, mesmo que falte. Todos os usuários + quantos pedidos têm (inclusive 0).
  2. Encontrar órfãos — linhas sem correspondência. Usuários sem pedidos. Produtos que ninguém nunca comprou. Publicações sem comentários.
  3. Contar lacunas nos dados. Quantas aulas não têm lição de casa, quantas publicações não têm comentários.

INNER JOIN não serve aqui — descarta as linhas "sem filhos" na hora.

Sintaxe básica

SELECT columns
FROM table_A         -- esquerda
LEFT JOIN table_B    -- direita
  ON A.key = B.key;

"Esquerda" é o que vem depois de FROM. "Direita" é o que vem depois de LEFT JOIN. Lembre-se da direção: LEFT significa que o lado esquerdo é totalmente preservado.

OUTER é opcional. LEFT JOIN e LEFT OUTER JOIN são a mesma coisa.

Exemplo: uma sala de aula

students:

idname
1Anna
2Boris
3Vera
4Grisha

grades (notas de prova):

idstudent_idscore
1015
1114
1223

Consulta: "cada aluno com as suas notas, se houver".

SELECT s.name, g.score
FROM students s
LEFT JOIN grades g ON s.id = g.student_id;

Resultado:

namescore
Anna5
Anna4
Boris3
VeraNULL
GrishaNULL

O que observar:

  • Os quatro alunos aparecem no resultado. Esse é todo o sentido do LEFT JOIN.
  • Anna tem duas notas — duas linhas.
  • Boris tem uma — uma linha.
  • Vera e Grisha não têm notas → uma linha cada um, com NULL em score.

Se tivéssemos escrito INNER JOIN, só restariam Anna (duas linhas) e Boris. Vera e Grisha cairiam — justamente as pessoas com quem a professora se importa.

Encontrar órfãos — linhas sem correspondência

Truque clássico. Para encontrar os alunos que não fizeram nenhuma prova, filtre por IS NULL:

SELECT s.name
FROM students s
LEFT JOIN grades g ON s.id = g.student_id
WHERE g.id IS NULL;

Resultado:

name
Vera
Grisha

Lógica: LEFT JOIN mantém cada aluno. Os que não têm notas têm NULL em g.id. WHERE g.id IS NULL fica apenas com eles.

Esse padrão (LEFT JOIN ... WHERE other.id IS NULL) é a forma padrão de encontrar "sem correspondência". É usado por toda parte: usuários sem pedidos, publicações sem comentários, produtos que ninguém comprou.

Não filtre a tabela direita no WHERE

A armadilha. Se você quer apenas as notas 5 e escreve:

SELECT s.name, g.score
FROM students s
LEFT JOIN grades g ON s.id = g.student_id
WHERE g.score = 5;

Resultado:

namescore
Anna5

Vera e Grisha caíram. Porque para eles WHERE g.score = 5 é avaliado como NULL = 5 (não TRUE) e eles são filtrados. O LEFT JOIN virou de fato um INNER JOIN.

Se você quer manter todos os alunos mas mostrar a nota apenas quando for um 5 — a condição vai no ON, não no WHERE:

SELECT s.name, g.score
FROM students s
LEFT JOIN grades g ON s.id = g.student_id AND g.score = 5;

Resultado:

namescore
Anna5
BorisNULL
VeraNULL
GrishaNULL

Agora os quatro estão no resultado; a nota aparece apenas quando é um 5. Uma diferença sutil mas crítica. Lembre-se: as condições sobre a tabela direita → ON; sobre a esquerda → WHERE.

INNER versus LEFT — visualizado

Imagine duas tabelas de um time de futebol: players e goals (gols marcados). Nem todo jogador marcou.

  • INNER JOIN → apenas os jogadores que marcaram pelo menos uma vez.
  • LEFT JOIN de players para goals → todos os jogadores; os que não marcaram têm NULL nas colunas de gols.
  • LEFT JOIN + WHERE goals.id IS NULL → apenas os jogadores que não marcaram de jeito nenhum.

Três perguntas diferentes — três consultas diferentes.

Exemplo maior: e-commerce

users:

idnamesignup_date
1Anna2024-01-15
2Boris2024-02-01
3Vera2024-02-20
4Grisha2024-03-10

orders:

iduser_idamountcreated_at
5015002024-02-05
51115002024-02-10
5222002024-02-25

Pedido de negócio: "quantos pedidos e quanto gastou no total cada usuário cadastrado? Inclua os que ainda não compraram nada".

SELECT
  u.name,
  COUNT(o.id)               AS orders_count,
  COALESCE(SUM(o.amount), 0) AS total_spent
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id, u.name
ORDER BY total_spent DESC;

Resultado:

nameorders_counttotal_spent
Anna22000
Boris1200
Vera00
Grisha00

Pontos-chave:

  • Aparecem os 4 usuários, inclusive Vera e Grisha com zero pedidos.
  • COUNT(o.id) retorna 0 para eles (NULL não conta no COUNT).
  • SUM retornaria NULL para eles, então o envolvemos em COALESCE(..., 0) — transformar NULL em 0 para uma saída limpa.

Uma consulta de painel do pão de cada dia: "atividade por usuário, inclusive o zero".

Erros comuns de iniciante

1. WHERE sobre a tabela direita, transformando sem querer LEFT em INNER. O erro mais comum e mais traiçoeiro. Os filtros sobre colunas do lado direito → ON. Os filtros sobre colunas do lado esquerdo → WHERE.

2. Assustar-se com os NULL no resultado. Não são um problema — são um sinal de "sem correspondência à direita". Use IS NULL, COALESCE, agregações que ignoram NULL, e você está bem.

3. Usar LEFT JOIN quando é preciso INNER. Se o negócio diz "apenas os usuários que TÊM pedidos" — isso é INNER JOIN. LEFT JOIN aqui dá linhas a mais e pode deixar a consulta mais lenta.

4. Empilhar vários LEFT JOIN e perder o fio. As cadeias de A LEFT JOIN B LEFT JOIN C são delicadas — cada nova condição é relativa ao que já existe. Para junções complexas, construa-as de forma incremental.

5. RIGHT JOIN em vez de trocar as tabelas. RIGHT JOIN existe e faz a imagem espelhada. Na prática quase ninguém o usa — simplesmente troque as tabelas e fique com LEFT JOIN. Mais fácil de ler.

6. COUNT(*) versus COUNT(column) depois de um LEFT JOIN. COUNT(*) conta todas as linhas, inclusive aquelas em que o lado direito é NULL. COUNT(o.id) conta apenas as correspondências reais. Com LEFT JOIN esses dão números diferentes.

Resumo rápido

  • LEFT JOIN mantém TODAS as linhas da tabela esquerda.
  • Se o lado direito não tem correspondência — as suas colunas ficam NULL.
  • LEFT JOIN ... WHERE other.id IS NULL é a forma padrão de encontrar as linhas sem correspondência.
  • As condições sobre o lado direito vão no ON; sobre o lado esquerdo, no WHERE.
  • OUTER é opcional; LEFT JOIN = LEFT OUTER JOIN.
  • Mais comum nas tarefas do mundo real do que INNER, porque você normalmente quer ver o quadro completo, inclusive os zeros.

Experimente você mesmo

Sobre users e orders acima:

  1. Liste TODOS os usuários com o número de pedidos que têm (inclusive o zero).
  2. Encontre os usuários sem nenhum pedido (padrão IS NULL).
  3. Liste TODOS os usuários com o seu pedido mais recente (se houver). Dica: LEFT JOIN + MAX(created_at) + GROUP BY.

Quando o LEFT JOIN faz sentido, abre-se toda uma classe de problemas que simplesmente não dá para resolver sem ele.

Pratique com exercícios reais

Resolva exercícios no treinador de SQL com correção instantânea e dicas.

Abrir o treinador