Profissional analisando gráficos e tabelas de dados em um notebook
JOIN reúne informações relacionadas para responder perguntas que uma única tabela não consegue responder. Crédito da foto.
Compartilhe este conteúdo

JOIN é o recurso do SQL usado para combinar linhas de duas ou mais tabelas relacionadas. Em vez de repetir o nome do cliente em cada pedido, por exemplo, o banco guarda o cliente em uma tabela, os pedidos em outra e utiliza uma chave para conectá-los. A consulta com JOIN reconstrói essas informações quando precisamos exibi-las.

O cenário: clientes e pedidos separados

Imagine uma loja com duas tabelas. A primeira registra cada cliente uma única vez. A segunda registra os pedidos e guarda em cliente_id a identificação do cliente responsável.

clientes Valor de exemplo
id 1
nome Ana
cidade Petrolina
pedidos Valor de exemplo
id 101
cliente_id 1
total 149,90

A ligação acontece entre clientes.id e pedidos.cliente_id. A primeira coluna normalmente é uma chave primária; a segunda, uma chave estrangeira.

INNER JOIN mostra somente correspondências

INNER JOIN retorna apenas os pares de linhas que satisfazem a condição escrita depois de ON. Clientes sem pedidos e pedidos sem cliente correspondente ficam fora do resultado.

SELECT c.nome, p.id AS pedido, p.total
FROM clientes AS c
INNER JOIN pedidos AS p
ON c.id = p.cliente_id;

Os nomes c e p são aliases: apelidos temporários que deixam a consulta menor e evitam ambiguidade. c.nome significa “coluna nome da tabela clientes”. Já p.id AS pedido renomeia a coluna apenas no resultado.

Como ler a consulta: parta de clientes, encontre os pedidos cujo cliente_id seja igual ao id do cliente e mostre nome, número do pedido e total.

LEFT JOIN preserva todas as linhas da esquerda

Quando a pergunta for “quais clientes fizeram pedido e quais ainda não fizeram?”, use LEFT JOIN. Todas as linhas da tabela à esquerda permanecem. Quando não há correspondência na direita, as colunas do pedido recebem NULL.

SELECT c.nome, p.id AS pedido, p.total
FROM clientes AS c
LEFT JOIN pedidos AS p
ON c.id = p.cliente_id
ORDER BY c.nome;

Essa diferença é importante: o INNER responde sobre os registros conectados; o LEFT também revela ausências. Para listar somente clientes sem pedidos, teste uma coluna da tabela direita:

SELECT c.id, c.nome
FROM clientes AS c
LEFT JOIN pedidos AS p
ON c.id = p.cliente_id
WHERE p.id IS NULL;

Filtro no ON ou no WHERE?

Em junções externas, mudar um filtro de lugar pode mudar o significado. Suponha que queremos manter todos os clientes e mostrar apenas os pedidos pagos:

SELECT c.nome, p.id, p.total
FROM clientes AS c
LEFT JOIN pedidos AS p
ON c.id = p.cliente_id
AND p.status = 'PAGO';

O filtro dentro de ON limita quais pedidos podem combinar, mas mantém todos os clientes. Se escrevermos WHERE p.status = 'PAGO', as linhas sem pedido terão status nulo e serão removidas; na prática, perde-se o objetivo de preservar todos os clientes.

RIGHT JOIN e FULL JOIN

RIGHT JOIN preserva todas as linhas da tabela à direita. Ele é o espelho do LEFT. Muitas equipes preferem reorganizar a ordem das tabelas e usar LEFT porque a leitura costuma ficar mais natural, mas ambos são válidos.

SELECT c.nome, p.id AS pedido
FROM clientes AS c
RIGHT JOIN pedidos AS p
ON c.id = p.cliente_id;

FULL JOIN preserva os dois lados: retorna correspondências, clientes sem pedidos e pedidos sem cliente correspondente. Ele é útil em auditorias e comparações entre conjuntos.

SELECT c.id AS cliente_id, c.nome, p.id AS pedido_id
FROM clientes AS c
FULL JOIN pedidos AS p
ON c.id = p.cliente_id;
Tipo O que permanece Uso típico
INNER JOIN Somente linhas correspondentes Pedidos com seus clientes
LEFT JOIN Todas da esquerda Clientes com ou sem pedido
RIGHT JOIN Todas da direita Preservar a segunda tabela
FULL JOIN Todas dos dois lados Auditoria de diferenças

Erros comuns ao usar JOIN

1. Esquecer a condição de junção

Combinar tabelas sem uma condição adequada pode produzir um produto cartesiano: cada linha de uma tabela é combinada com todas as linhas da outra. O resultado cresce rapidamente e geralmente não representa a pergunta desejada.

2. Relacionar colunas erradas

As colunas comparadas precisam representar o mesmo fato. Relacionar clientes.id com pedidos.id apenas porque ambas se chamam id está incorreto; o vínculo está em pedidos.cliente_id.

3. Usar SELECT *

Em uma consulta com várias tabelas, * pode trazer colunas repetidas e dados desnecessários. Selecione explicitamente o que será usado.

4. Ignorar duplicações legítimas

Um cliente com três pedidos aparecerá três vezes. Isso não é necessariamente erro: cada linha representa uma combinação cliente–pedido. Antes de aplicar DISTINCT, entenda a cardinalidade e defina se você quer detalhes ou um resumo.

Exemplo completo com total por cliente

Para exibir todos os clientes, a quantidade de pedidos e o valor total comprado, combinamos LEFT JOIN com agregação:

SELECT
c.id,
c.nome,
COUNT(p.id) AS quantidade_pedidos,
COALESCE(SUM(p.total), 0) AS total_comprado
FROM clientes AS c
LEFT JOIN pedidos AS p
ON c.id = p.cliente_id
GROUP BY c.id, c.nome
ORDER BY total_comprado DESC;

COUNT(p.id) conta apenas pedidos existentes. SUM soma os valores e COALESCE troca o resultado nulo por zero para clientes sem compras. Antes desse passo, revise como filtrar e ordenar resultados em SQL.

Desafio prático

Crie as tabelas categorias e produtos. Depois escreva: (1) um INNER JOIN que mostre produto e categoria; (2) um LEFT JOIN que também mostre categorias sem produtos; e (3) uma consulta que conte quantos produtos existem em cada categoria.

Antes do JOIN, preveja quantas linhas podem aparecer

Se um cliente possui três pedidos, um JOIN entre clientes e pedidos produzirá três linhas para esse cliente. Isso não é duplicação acidental: cada linha representa uma correspondência diferente. O erro acontece quando a condição relaciona colunas inadequadas ou omite parte de uma chave composta.

PerguntaJOIN adequadoResultado esperado
Somente clientes que compraramINNER JOINUma linha por correspondência
Todos os clientes, inclusive sem pedidoLEFT JOINCliente sem pedido aparece com NULL
Registros sem par nos dois ladosFULL JOIN com filtro de NULLLinhas órfãs de ambas as tabelas

Roteiro para auditar uma junção

  1. Conte as linhas de cada tabela antes da junção.
  2. Confirme a cardinalidade esperada: um para um, um para muitos ou muitos para muitos.
  3. Liste a chave de relacionamento e verifique valores nulos ou órfãos.
  4. Execute primeiro apenas as chaves, sem SELECT *.
  5. Investigue qualquer multiplicação inesperada antes de aplicar DISTINCT.

DISTINCT pode esconder o sintoma sem corrigir a causa. A documentação do PostgreSQL apresenta os tipos de junção e mostra por que um filtro no ON pode gerar resultado diferente do mesmo filtro no WHERE em junções externas.

Desafio com previsão

Crie três clientes: um com dois pedidos, um com um e um sem pedidos. Antes de executar, escreva quantas linhas espera em INNER JOIN e LEFT JOIN. Depois adicione dois itens a cada pedido e faça outra junção. Explique por que a quantidade de linhas mudou.

Perguntas frequentes

JOIN precisa de chave estrangeira?

O SQL consegue combinar colunas mesmo sem uma restrição de chave estrangeira, mas a chave documenta o relacionamento e ajuda a impedir referências inválidas. Em um projeto bem estruturado, ela normalmente deve existir.

ON e USING são iguais?

USING (coluna) é um atalho quando a coluna de ligação tem o mesmo nome nas duas tabelas. ON é mais geral, explícito e permite condições diferentes.

Qual JOIN devo aprender primeiro?

Comece por INNER e LEFT. Eles resolvem grande parte das consultas iniciais e deixam clara a diferença entre exigir correspondência e preservar linhas sem correspondência.

Referências bibliográficas

Obras reconhecidas utilizadas para fundamentar os conceitos e exemplos deste artigo.

  1. BEAULIEU, Alan. Learning SQL . 3. ed. O’Reilly Media, 2020.
  2. ELMASRI, Ramez; NAVATHE, Shamkant B. Fundamentals of Database Systems . 7. ed. Pearson, 2016.

Documentação técnica: PostgreSQL Global Development Group. Table Expressions — Joined Tables. Acesso em 22 ago. 2026.

Consulte a bibliografia completa do Código em Sala.