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 leituraReferenceSQL · 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:

id name
1 Anna
2 Boris
3 Vera
4 Grisha

grades (notas de prova):

id student_id score
10 1 5
11 1 4
12 2 3

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:

name score
Anna 5
Anna 4
Boris 3
Vera NULL
Grisha NULL

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:

name score
Anna 5

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:

name score
Anna 5
Boris NULL
Vera NULL
Grisha NULL

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:

id name signup_date
1 Anna 2024-01-15
2 Boris 2024-02-01
3 Vera 2024-02-20
4 Grisha 2024-03-10

orders:

id user_id amount created_at
50 1 500 2024-02-05
51 1 1500 2024-02-10
52 2 200 2024-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:

name orders_count total_spent
Anna 2 2000
Boris 1 200
Vera 0 0
Grisha 0 0

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