FNSP Web Page

LEFT JOIN: o erro que o transforma num INNER JOIN

Escreve-se um LEFT JOIN precisamente para incluir as linhas que não têm par do outro lado. E depois acrescenta-se uma condição no WHERE que as deita todas fora, sem uma palavra de aviso.

1. O que se queria

-- Todos os artigos, com o número de comentários aprovados
SELECT a.titulo, count(c.id) AS comentarios
FROM artigos a
LEFT JOIN comentarios c ON c.artigo_id = a.id
GROUP BY a.id;

Um artigo sem comentários aparece com zero. É para isso que serve o LEFT.

2. O que se escreve, e estraga

SELECT a.titulo, count(c.id) AS comentarios
FROM artigos a
LEFT JOIN comentarios c ON c.artigo_id = a.id
WHERE c.aprovado = true          -- ← aqui
GROUP BY a.id;

Os artigos sem comentários trazem NULL nas colunas de c. E NULL = true não é verdadeiro — é desconhecido. O WHERE deita-os fora, e o LEFT JOIN passou a comportar-se como um INNER JOIN.

3. A correção

A condição sobre a tabela da direita pertence ao ON, e não ao WHERE:

SELECT a.titulo, count(c.id) AS comentarios
FROM artigos a
LEFT JOIN comentarios c
  ON c.artigo_id = a.id
  AND c.aprovado = true          -- ← faz parte da junção
GROUP BY a.id;

A regra em duas linhas: o ON decide o que emparelha; o WHERE decide que linhas ficam depois de emparelhadas. Numa junção à esquerda, é uma diferença que muda o resultado.

4. Onde o WHERE ainda faz sentido

Para condições sobre a tabela da esquerda, não há problema nenhum:

WHERE a.publicado_em >= '2026-01-01'

E há um uso deliberado do WHERE com nulos, que é procurar exatamente o que não tem par:

-- Artigos sem um único comentário
SELECT a.titulo
FROM artigos a
LEFT JOIN comentarios c ON c.artigo_id = a.id
WHERE c.id IS NULL;

É o mesmo mecanismo — desta vez usado de propósito.

Comentários

Ainda ninguém comentou este artigo.

Voltar ao blog

Gostávamos de saber quantas pessoas visitam o site, com o Google Analytics. Sem a sua autorização não corre nada. Política de Privacidade.