Voltar para a lista de artigos Artigos
7 minutos de leitura

Como Manter Linhas Inigualáveis de Duas Mesas em um JOIN SQL

Você quer juntar duas tabelas em SQL sem remover linhas inigualáveis? Você quer manter linhas inigualáveis de uma ou ambas as tabelas? Neste artigo, explicarei como manter todos os registros que você deseja usando os JOINs externos, tais como LEFT JOIN, RIGHT JOIN, e FULL JOIN. Exemplos incluídos!

O SQL JOIN é uma ferramenta poderosa que ajuda você a combinar dados de várias tabelas de seu banco de dados. Esta é uma idéia central por trás de bancos de dados relacionais - armazenar dados em diferentes tabelas inter-relacionadas e combinar dados destas tabelas quando necessário para análise de dados e relatórios. Se você precisar de uma recapitulação sobre como juntar tabelas em SQL, confira este guia para iniciantes e nosso guia interativo Cláusulas JOIN em SQL curso.

Infelizmente, quando você está apenas começando com SQL, as consultas JOIN podem produzir resultados frustrantes. Por exemplo, você pode obter duplicatas, dados ausentes, valores NULL inesperados, etc. Neste artigo, quero me concentrar no caso em que você deseja manter linhas inigualáveis de duas tabelas, mas um SQL JOIN as remove. Veremos porque isso acontece e como obter a saída que você espera.

Vamos começar com um exemplo.

Digamos que você esteja planejando uma campanha de marketing onde você dá um bônus especial a um conjunto de seus clientes. Há vários critérios para que um cliente seja elegível para o bônus. Para esta campanha em particular, você procura clientes que tenham pedidos com o status "Concluído" do último mês, mas que não tenham ganho em sua campanha de marketing anterior.

Você deseja combinar as informações das três tabelas a seguir:

customers
idfirst_namelast_nameemail
101KateWilsonkate101@gmail.com
102MariaWhitemaria102@gmail.com
103JohnSmithjohn103@gmail.com
104PhilipStevensphilip104@gmail.com

orders
idorder_datecustomer_idstaff_idorder_status
102022-01-19102301Completed
112022-01-20104301Completed
122022-01-25101304Completed
132022-01-31110302Completed

last_campaign_participants
campaign_idcustomer_idwinner
222104True
222101False
222110False

Você pode usar a seguinte consulta para juntar-se a estas tabelas e obter uma lista de clientes com as informações adicionais que você precisa:

SELECT 
  c.id, 
  c.first_name, 
  c.last_name, 
  o.order_status, 
  lcp.winner
FROM customers c
JOIN orders o
ON c.id = o.customer_id
JOIN last_campaign_participants lcp
ON c.id = lcp.customer_id;

Se você não tiver certeza de como esta consulta funciona, verifique nosso curso interativo com 93 desafios de codificação cobrindo diferentes tipos de JOINs.

Aqui está a saída da consulta SQL acima:

idfirst_namelast_nameorder_statuswinner
101KateWilsonCompletedfalse
104PhilipStevensCompletedtrue

Como você vê, a saída inclui apenas dois de cada quatro clientes. Isto porque somente estes dois clientes têm registros correspondentes em todas as três tabelas, e JOIN ou INNER JOIN produz somente as linhas combinadas. Com esta saída, vemos apenas um cliente elegível para a próxima campanha - Kate Wilson (ID 101). O outro foi o vencedor de nossa última campanha e, portanto, não se qualifica para esta campanha.

Mas será que podemos perder alguém removendo as filas inigualáveis? Na verdade, sim. Podemos ignorar os clientes que completaram pedidos mas não participaram de maneira alguma da última campanha. Estes clientes estão faltando nesta tabela. Queremos todos os clientes na saída do SQL JOIN, e depois filtrar os resultados conforme necessário.

Felizmente, SQL tem JOINs externos que permitem manter filas inigualáveis de duas tabelas.

JOINs internos vs. JOINs externos

Em contraste com INNER JOIN, ou apenas JOIN, que só retorna as linhas correspondentes de duas tabelas, os JOINs externos também retornam as linhas inigualáveis em SQL. Existem vários tipos de JOINs externos:

  • Um LEFT JOIN retorna todos os registros da tabela da esquerda (primeira), mesmo que não haja correspondências na tabela da direita (segunda).
  • A RIGHT JOIN retorna todos os registros da tabela da direita (segunda) mesmo que não haja correspondências na tabela da esquerda (primeira).
  • Um FULL JOIN retorna todos os registros de ambas as tabelas, incluindo os inigualáveis de qualquer uma delas.

Este artigo explica estes tipos de SQL JOIN em mais detalhes com exemplos e ilustrações. Veja também este ótimo Cláusulas JOIN em SQL Cheat Sheet para obter todas as nuances da sintaxe.

Para usar um JOIN externo, basta substituir a palavra-chave JOIN pela palavra-chave LEFT JOIN, RIGHT JOIN, ou FULL JOIN, dependendo do seu caso. Entretanto, observe que para LEFT JOIN e RIGHT JOIN, a ordem das tabelas na consulta SQL é importante.

Agora, vamos modificar nossa primeira consulta para manter filas inigualáveis e colocar todos os clientes na saída. Uma opção é usar LEFT JOIN enquanto nos certificamos de que o customers A tabela é listada primeiro na consulta (ou seja, logo após a palavra-chave FROM ):

SELECT 
  c.id, 
  c.first_name, 
  c.last_name, 
  o.order_status, 
  lcp.winner
FROM customers c
LEFT JOIN orders o
ON c.id = o.customer_id
LEFT JOIN last_campaign_participants lcp
ON c.id = lcp.customer_id;

A saída desta consulta inclui uma lista de todos os clientes atuais com as informações adicionais correspondentes das duas outras tabelas. Note que se nenhum registro corresponder ao cliente da tabela da esquerda, estes registros ainda estão incluídos, mas com valores NULL nas respectivas colunas:

idfirst_namelast_nameorder_statuswinner
101KateWilsonCompletedfalse
102MariaWhiteCompletedNULL
103JohnSmithNULLNULL
104PhilipStevensCompletedtrue

Ao manter as linhas inigualáveis com um LEFT JOIN, identificamos outro cliente que é elegível para a campanha. Especificamente, Maria White (ID 102) completou pedidos e não participou da última campanha - portanto, obviamente não ganhou.

Para entender melhor os JOINs externos, vamos ver mais alguns exemplos.

Exemplos de Juntas Externas

Agora, imagine que nós administramos uma livraria. Queremos comparar dois grupos de clientes: aqueles que compraram Harry Potter e a Pedra Filosofal e aqueles que compraram Harry Potter e a Câmara dos Segredos. Estas são as mesmas pessoas? Há alguém que comprou um livro, mas não outro? Talvez queiramos recomendar-lhes o outro livro.

philosophers_stone
product_idcustomer_idfirst_namelast_name
11301AndyBernard
11303RobertCalifornia
11305PamBeesley
11306OscarMartinez

chamber_of_secrets
product_idcustomer_idfirst_namelast_name
12301AndyBernard
12302KevinMalone
12305PamBeesley

Exemplo com o JOGO ESQUERDA

Primeiro, queremos ver todos os que compraram Harry Potter e a Pedra Filosofal de nós e verificar se eles também compraram Harry Potter e a Câmara dos Segredos.

Para obter esta saída, usamos LEFT JOIN com uma lista daqueles que compraram o primeiro livro incluído na cláusula FROM da consulta (tabela da esquerda).

SELECT 
  ps.product_id, 
  ps.first_name, 
  ps.last_name, 
  cs.product_id, 
  cs.first_name, 
  cs.last_name
FROM philosophers_stone ps
LEFT JOIN chamber_of_secrets cs
ON ps.customer_id = cs.customer_id;

Isto nos permite manter todos os compradores de Harry Potter e da Pedra Filosofal, mesmo que não haja registros correspondentes na segunda tabela:

product_idfirst_namelast_nameproduct_idfirst_namelast_name
11AndyBernard12AndyBernard
11RobertCaliforniaNULLNULLNULL
11PamBeesley12PamBeesley
11OscarMartinezNULLNULLNULL

Agora, vemos que dois clientes compraram o primeiro livro da série, mas não o segundo. Podemos recomendar o segundo livro a eles em nossa próxima campanha de marketing.

Exemplo com o FULL JOIN

Mas e se houver clientes que tenham comprado apenas o segundo livro, mas não o primeiro? Isso também seria bom saber.

Em vez de escrever uma pergunta separada para identificar este grupo de clientes, é melhor usar FULL JOIN que nos fornece o quadro completo: aqueles que compraram apenas o primeiro livro, aqueles que compraram apenas o segundo livro, e aqueles que compraram ambos os livros:

SELECT 
  ps.product_id, 
  ps.first_name, 
  ps.last_name, 
  cs.product_id, 
  cs.first_name, 
  cs.last_name
FROM philosophers_stone ps
FULL JOIN chamber_of_secrets cs
ON ps.customer_id = cs.customer_id;
product_idfirst_namelast_nameproduct_idfirst_namelast_name
11AndyBernard12AndyBernard
11RobertCaliforniaNULLNULLNULL
11PamBeesley12PamBeesley
11OscarMartinezNULLNULLNULL
NULLNULLNULL12KevinMalone

Parece ótimo! Agora podemos comparar facilmente dois grupos de clientes e encontrar oportunidades para boas recomendações de livros. Os Outer JOINs podem ser super úteis!

Hora de Praticar Cláusulas JOIN em SQL!

Juntar tabelas é uma das habilidades fundamentais necessárias para o uso eficaz do SQL na análise de dados e relatórios. Não é tão difícil, mas você precisa de muita prática com Cláusulas JOIN em SQL para evitar armadilhas como a falta de registros e duplicatas inesperadas.

Eu recomendo começar com a Cláusulas JOIN em SQL curso interativo. Ele cobre todos os tipos chave de JOINs, unindo uma tabela consigo mesmo, unindo várias tabelas em uma consulta, e unindo tabelas em colunas não chave. Obtenha mais detalhes sobre este curso neste artigo de visão geral.

Bônus. Aqui estão as 10 principais perguntas da entrevista SQL JOIN com respostas.

Obrigado por ler, e feliz aprendizado!