
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.
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.
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.
- BEAULIEU, Alan. Learning SQL. 3. ed. O’Reilly Media, 2020.
- 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.