SQL RIGHT JOIN
Na aula LEFT JOIN, a tabela da esquerda ficava inteira. O RIGHT JOIN, a "junção pela direita", é o espelho dele: a tabela que fica inteira é a da direita, a que vem depois da palavra JOIN. Ele não faz nada que o LEFT JOIN não faça (basta trocar as tabelas de lugar), e por isso muita gente nunca o usa. Mas você vai encontrá-lo em consultas de outras pessoas, e há situações em que ele deixa a consulta mais simples de escrever. Nesta aula, a Ana usa os dois e aprende a converter um no outro.
- O que o
RIGHT JOINguarda: todas as linhas da tabela da direita. - Os clientes sem pedido e os produtos nunca vendidos, agora com
RIGHT JOIN. - A forma antiga, que funciona em qualquer banco: trocar a ordem das tabelas e usar
LEFT JOIN. - Quando o
RIGHT JOINajuda: pendurar, no fim de uma consulta pronta, uma tabela da qual você quer todas as linhas. - Desde quando o SQLite tem
RIGHT JOIN(3.39.0) e o que os outros bancos recomendam. - As armadilhas, inclusive o erro de digitação que o SQLite aceita calado.
Os exemplos rodam de verdade no seu navegador, no banco da Loja Aurora.
A ideia: a mesma lista, lida do outro lado
Volte à lista de chamada da aula passada: todos os alunos, com a nota ao lado, e espaço em branco para quem faltou. Agora imagine que a professora escreveu a lista ao contrário, com as notas na coluna da esquerda e os nomes na da direita. A lista é a mesma; só mudou o lado em que estão os nomes. No RIGHT JOIN, a "lista de chamada" (a tabela que aparece inteira) fica do lado direito.
clientes LEFT JOIN pedidospedidos RIGHT JOIN clientesNos dois desenhos, o círculo pintado é o dos clientes: os dois JOINs guardam todos os clientes. O que mudou foi só o lado em que clientes foi escrito.
1. O primeiro RIGHT JOIN
Todos os clientes, com os seus pedidos, começando a consulta pela tabela de pedidos. Clientes a partir do 26:
SELECT c.id, c.nome, p.id AS pedido FROM pedidos p RIGHT JOIN clientes c ON p.cliente_id = c.id WHERE c.id >= 26 ORDER BY c.id, p.id;
- FROM pedidos p
- A tabela da esquerda. Desta vez, é ela que pode ficar com buracos (
NULL). - RIGHT JOIN clientes c
- Right join = "junção pela direita". A tabela da direita,
clientes, aparece inteira. Também se escreveRIGHT OUTER JOIN. - ON p.cliente_id = c.id
- A regra do par, a mesma de sempre. No
ON, a ordem dos dois lados do=não importa.
O resultado é idêntico ao do clientes LEFT JOIN pedidos da aula passada: a Mirela com os 3 pedidos dela, e os clientes 27 a 30 com pedido em NULL. Na loja inteira, também são 94 linhas:
SELECT COUNT(*) FROM pedidos p RIGHT JOIN clientes c ON p.cliente_id = c.id;
Com SELECT *, dá para ver bem onde ficam os buracos: as colunas de pedidos vêm primeiro (a tabela do FROM), todas em NULL para o Paulo, e as de clientes depois:
SELECT * FROM pedidos p RIGHT JOIN clientes c ON p.cliente_id = c.id WHERE c.id = 27;
2. Quem não tem par, com RIGHT JOIN
O padrão "quem nunca…" funciona igual, com o teste de NULL agora na tabela da esquerda:
SELECT c.id, c.nome FROM pedidos p RIGHT JOIN clientes c ON p.cliente_id = c.id WHERE p.id IS NULL;
Os mesmos quatro clientes sem pedido. E os produtos nunca vendidos:
SELECT pr.id, pr.nome FROM itens_pedido i RIGHT JOIN produtos pr ON i.produto_id = pr.id WHERE i.produto_id IS NULL;
Experimente: esta consulta procura clientes sem pedido, mas usa um JOIN comum e por isso não acha ninguém. Troque o tipo de JOIN para que os clientes (a tabela da direita) apareçam todos, e o filtro encontre os 4 que nunca compraram. Não mude a ordem das tabelas.
SELECT c.id, c.nome FROM pedidos p JOIN clientes c ON p.cliente_id = c.id WHERE p.id IS NULL;
SELECT c.id, c.nome FROM pedidos p RIGHT JOIN clientes c ON p.cliente_id = c.id WHERE p.id IS NULL;
3. A forma antiga: trocar a ordem e usar LEFT JOIN
Todo RIGHT JOIN pode ser reescrito como LEFT JOIN: basta trocar as duas tabelas de lugar. A regra do ON continua a mesma.
| Com RIGHT JOIN | A mesma coisa com LEFT JOIN |
|---|---|
FROM pedidos p | FROM clientes c |
FROM itens_pedido i | FROM produtos pr |
Confira, com a primeira linha da tabela:
SELECT c.id, c.nome FROM clientes c LEFT JOIN pedidos p ON p.cliente_id = c.id WHERE p.id IS NULL;
O mesmo resultado do RIGHT JOIN da seção 2. Essa troca era a única forma de fazer um "RIGHT JOIN" no SQLite até 2022: o RIGHT JOIN e o FULL JOIN só chegaram na versão 3.39.0, de 25 de junho de 2022. As notas daquela versão dizem, em inglês, "acrescenta o suporte (há muito esperado) a RIGHT e FULL OUTER JOIN". O editor do guia e o terminal da Ana usam uma versão bem mais nova:
SELECT sqlite_version();
$ sqlite3 --version 3.50.4 2025-07-30 19:33:53 4d8adfb30e03f9cf27f800a2c1ba3c48fb4ca1b08b0f5ed59a4d5ecbf45e20a3 (64-bit)
Se você for usar um SQLite mais antigo que a 3.39.0 (em sistemas antigos, ou dentro de programas que trazem o SQLite embutido), o RIGHT JOIN não vai funcionar lá. A troca de ordem funciona em qualquer versão de qualquer banco.
4. Quando o RIGHT JOIN ajuda
O caso em que o RIGHT JOIN brilha é quando você já tem uma consulta montada e quer pendurar no fim uma tabela da qual precisa de todas as linhas. A Ana tem esta consulta, que junta os itens com os pedidos de 2026:
FROM itens_pedido i JOIN pedidos p ON i.pedido_id = p.id AND p.data >= '2026-01-01'
Agora ela quer saber quantas vezes cada produto de jardinagem foi vendido em 2026, inclusive os que não venderam nada. Em vez de reorganizar a consulta toda, ela pendura produtos no fim com RIGHT JOIN:
SELECT pr.nome AS produto, COUNT(i.pedido_id) AS vendas_2026 FROM itens_pedido i JOIN pedidos p ON i.pedido_id = p.id AND p.data >= '2026-01-01' RIGHT JOIN produtos pr ON i.produto_id = pr.id WHERE pr.categoria_id = 8 GROUP BY pr.id, pr.nome;
- FROM itens_pedido i JOIN pedidos p ON … AND p.data >= '2026-01-01'
- Primeiro passo: só os itens de pedidos de 2026.
- RIGHT JOIN produtos pr ON i.produto_id = pr.id
- Segundo passo: o resultado do primeiro (à esquerda) junta-se com todos os produtos (à direita). Produto sem item em 2026 fica com
NULLdo lado dos itens. - COUNT(i.pedido_id)
- Conta só os itens de verdade, então quem não vendeu fica com 0 (a regra do
COUNTda aula LEFT JOIN).
Em 2026, o regador e o kit de sementes venderam uma vez cada; os outros três, nenhuma. Com LEFT JOIN, a mesma consulta precisaria começar por produtos, encadear dois LEFT JOIN (itens e pedidos, com a data no ON do segundo) e contar p.id em vez de i.pedido_id. Os dois jeitos estão certos; o RIGHT JOIN, aqui, só poupou trabalho.
Formas diferentes de fazer a mesma coisa
| Forma | Quando usar |
|---|---|
FROM a LEFT JOIN b | O padrão. Quase todo mundo lê consultas da esquerda para a direita, com a tabela principal no FROM. Funciona em todos os bancos e em qualquer versão do SQLite. |
FROM b RIGHT JOIN a | Quando você pendura, no fim de uma consulta pronta, a tabela da qual quer todas as linhas. Exige SQLite 3.39.0 ou mais novo. |
Misturar LEFT e RIGHT na mesma consulta | Evite: fica difícil saber qual tabela fica inteira. Reescreva tudo como LEFT JOIN. |
MySQL, PostgreSQL e SQL Server têm RIGHT JOIN e RIGHT OUTER JOIN, com o mesmo comportamento. A documentação do MySQL diz que o RIGHT JOIN funciona de forma análoga ao LEFT JOIN e recomenda: "para manter o código portável entre bancos de dados, é recomendado usar LEFT JOIN em vez de RIGHT JOIN". Ou seja, a própria documentação aconselha a forma antiga, a troca de ordem.
Quando dá errado
WHERE
A mesma armadilha do LEFT JOIN, só que espelhada: agora o lado com buracos é o da esquerda. A Ana quer todos os clientes a partir do 26, com os pedidos de 2026:
SELECT c.id, c.nome, p.id AS pedido FROM pedidos p RIGHT JOIN clientes c ON p.cliente_id = c.id WHERE c.id >= 26 AND p.data >= '2026-01-01';
O que acontece: só a Mirela. Os clientes 27 a 30 têm p.data em NULL, e o WHERE os jogou fora: o RIGHT JOIN virou, na prática, um INNER JOIN.
Como consertar: o filtro da tabela que pode ficar vazia (aqui, pedidos) vai para o ON: RIGHT JOIN clientes c ON p.cliente_id = c.id AND p.data >= '2026-01-01'.
IS NULL do lado errado
No RIGHT JOIN, os buracos ficam na tabela da esquerda. WHERE c.id IS NULL (na tabela que fica inteira) nunca é verdadeiro e devolve 0 linhas, sem erro. Como consertar: teste a chave da tabela do FROM: WHERE p.id IS NULL. Se você se pega confundindo os lados, reescreva com LEFT JOIN.
A Ana digitou RIGTH em vez de RIGHT, e escreveu a coluna do ON sem a tabela:
SELECT COUNT(*) FROM pedidos RIGTH JOIN clientes ON cliente_id = clientes.id;
O que acontece: nenhum erro, e 90 linhas, não 94. O SQLite leu pedidos RIGTH como "a tabela pedidos com o apelido RIGTH" (lembre: o AS do apelido é opcional), seguido de um JOIN comum. A consulta virou um INNER JOIN, e os clientes sem pedido sumiram.
Se a tabela já tem apelido, o mesmo erro de digitação gera mensagem, porque não cabe um segundo apelido:
SELECT COUNT(*) FROM pedidos p RIGTH JOIN clientes c ON p.cliente_id = c.id;
A mensagem: near "RIGTH": syntax error. E se a consulta usar o nome da tabela no ON (pedidos.cliente_id) sem apelido, a mensagem é no such column: pedidos.cliente_id, porque a tabela passou a se chamar RIGTH.
Como evitar: dê apelido a toda tabela num JOIN e escreva toda coluna com o apelido na frente. Assim, um erro de digitação no tipo de JOIN vira mensagem, em vez de resultado errado.
JOIN
SELECT COUNT(*) FROM pedidos p RIGHT clientes c ON p.cliente_id = c.id;
A mensagem: near "ON": syntax error. Sem a palavra JOIN, o SQLite não reconhece a junção e se perde ao chegar no ON. Como consertar: RIGHT JOIN clientes c.
ON
Como nos outros JOINs, o SQLite aceita FROM pedidos p RIGHT JOIN clientes c sem condição e devolve todos os pares: 2.700 linhas. No MySQL, no PostgreSQL e no SQL Server, um RIGHT JOIN sem condição dá erro de sintaxe.
Referência rápida
| Escrita | O que faz |
|---|---|
a RIGHT JOIN b ON … | Todas as linhas de b; as que não têm par em a vêm com NULL nas colunas de a |
RIGHT OUTER JOIN | O mesmo que RIGHT JOIN |
a RIGHT JOIN b = b LEFT JOIN a | Trocar a ordem das tabelas converte um no outro (o ON fica igual) |
… WHERE a.chave IS NULL | Só as linhas de b sem par |
SELECT sqlite_version(); | Mostra a versão do SQLite (o RIGHT JOIN exige 3.39.0 ou mais) |
| Mensagem ou sintoma | Quer dizer |
|---|---|
near "RIGTH": syntax error | Erro de digitação no tipo de JOIN (com apelido na tabela) |
(nenhuma) linhas de menos com RIGTH JOIN | Sem apelido, a palavra errada virou apelido, e o JOIN virou INNER |
near "ON": syntax error | Faltou a palavra JOIN depois de RIGHT |
| (nenhuma) as linhas sem par sumiram | Filtro na tabela da esquerda no WHERE |
Exercícios
1. Converta para LEFT JOIN
Reescreva FROM pedidos p RIGHT JOIN clientes c ON p.cliente_id = c.id com LEFT JOIN:
2. A versão
A partir de qual versão o SQLite aceita RIGHT JOIN?
3. Em FROM itens_pedido i RIGHT JOIN produtos pr ON i.produto_id = pr.id, qual tabela aparece inteira?
4. O que a documentação do MySQL recomenda sobre RIGHT JOIN?
5. SELECT COUNT(*) FROM pedidos RIGTH JOIN clientes ON cliente_id = clientes.id; (com o erro de digitação) devolve 90, sem erro. Por quê?
Missão final: todos os funcionários, pela direita
Missão: mostre os 8 funcionários com quantos pedidos cada um atendeu, inclusive os que atenderam 0. A consulta deve continuar começando por FROM pedidos p: use RIGHT JOIN para que funcionarios fique inteira, e conte de forma que quem não atendeu ninguém fique com 0.
SELECT f.nome AS funcionario, COUNT(*) AS pedidos FROM pedidos p JOIN funcionarios f ON p.funcionario_id = f.id GROUP BY f.id, f.nome;
SELECT f.nome AS funcionario, COUNT(p.id) AS pedidos FROM pedidos p RIGHT JOIN funcionarios f ON p.funcionario_id = f.id GROUP BY f.id, f.nome;
É o mesmo resultado da missão final do LEFT JOIN, por outro caminho. E se você quisesse, numa consulta só, todos os clientes e todos os pedidos, sobrando gente dos dois lados? Aí nem o LEFT nem o RIGHT bastam: é o FULL JOIN.
Resumo
RIGHT JOINmostra todas as linhas da tabela da direita (a que vem depois deJOIN); as sem par vêm comNULLnas colunas da esquerda.a RIGHT JOIN bdá o mesmo queb LEFT JOIN a. Trocar a ordem é a forma antiga, que funciona em qualquer banco e versão.- O SQLite tem
RIGHT JOINdesde a versão 3.39.0 (junho de 2022). O guia usa a 3.50.4. - O MySQL recomenda
LEFT JOINno lugar deRIGHT JOIN, por portabilidade. Use oRIGHTquando ele poupar trabalho, como ao pendurar uma tabela no fim de uma consulta pronta. - As armadilhas são as do
LEFT JOIN, espelhadas: o filtro da tabela da esquerda vai noON, e oIS NULLtesta a chave da esquerda. - Dê apelido a toda tabela: assim, um
RIGTHdigitado errado vira mensagem de erro, e não um apelido.