12th Dec 2022 10 minutos de leitura Como você se livra de duplicatas em um SQL JOIN? Kateryna Koidan sql aprender sql sql joins Índice Cláusulas JOIN em SQL Visão geral . Quais são as razões para duplicatas em Cláusulas JOIN em SQL? 1. Condição de Falta 2. Usando uma condição Incompleta ON 3. Selecionando um sub-conjunto de colunas 4. Listando apenas as linhas de correspondência 5. Usando a Auto-Adesão Vamos praticar Cláusulas JOIN em SQL! Você tem duplicatas indesejadas de sua consulta SQL JOIN? Neste artigo, discutirei os possíveis motivos para obter duplicatas após juntar tabelas em SQL e mostrarei como consertar uma consulta, dependendo do motivo por trás das duplicatas. Analistas de dados com pouca experiência em Cláusulas JOIN em SQL frequentemente encontram duplicatas indesejadas no conjunto de resultados. É um desafio para iniciantes identificar o motivo por trás dessas duplicatas em JOINs. A melhor maneira de aprender Cláusulas JOIN em SQL é através da prática. Eu recomendo o Cláusulas JOIN em SQL curso. Ele contém mais de 90 exercícios que fazem você praticar os diferentes tipos de JOIN em SQL. Neste artigo, vou discutir as questões mais comuns que levam às duplicatas nas saídas SQL JOIN. Também vou mostrar possíveis soluções para estas questões comuns. Vamos começar com uma breve visão geral de Cláusulas JOIN em SQL. Cláusulas JOIN em SQL Visão geral . JOIN é uma construção SQL para solicitar informações de duas ou mais tabelas dentro da mesma consulta. Por exemplo, digamos que você tenha uma lista dos 100 melhores filmes do século 20, e você queira subestimá-la aos filmes feitos por diretores vivos atualmente. Em seu movies tabela, você não tem informações detalhadas sobre os diretores de cinema, apenas suas identificações. Mas você tem uma tabela separada directors tabela, com a identificação, o nome completo, o ano de nascimento e o ano da morte (se aplicável) de cada diretor. Em sua consulta, você pode unir duas tabelas pelo ID do diretor para obter uma lista de filmes feitos por diretores vivos atualmente: SELECT movies.title, directors.full_name FROM movies JOIN directors ON movies.director_id = directors.id WHERE directors.death_year IS NULL; Como você pode ver, nós especificamos as tabelas que queremos unir nas cláusulas FROM e JOIN. Em seguida, na cláusula ON, especificamos as colunas de cada tabela a serem utilizadas para unir-se a estas tabelas. Se você é novo no Cláusulas JOIN em SQL, confira este guia introdutório. Aqui está também uma folha de consultas SQL JOIN com sintaxe e exemplos de diferentes JOINs. O SQL JOIN é uma grande ferramenta que fornece uma variedade de opções além da simples junção de duas tabelas. Se você não estiver familiarizado com os tipos de SQL JOIN, leia este artigo que os explica com ilustrações e exemplos. Dependendo de seu caso de uso, você pode escolher INNER JOIN, LEFT JOIN, RIGHT JOIN, e FULL JOIN. Você pode até mesmo precisar juntar tabelas sem uma coluna comum ou juntar mais de duas tabelas. Agora, vamos ver como estas diferentes uniões podem resultar em duplicatas indesejadas. Quais são as razões para duplicatas em Cláusulas JOIN em SQL? Há muitas razões possíveis para obter duplicatas no resultado de sua consulta SQL JOIN. Vou analisar as 5 principais razões; para cada uma delas, mostrarei uma consulta de amostra com o problema e uma consulta corrigida para obter um resultado sem duplicatas. Vamos começar revendo brevemente os dados a serem utilizados para nossos exemplos. Imagine que administramos uma agência imobiliária que vende casas em algum lugar nos Estados Unidos. Temos tabelas com agents, customerse sales. Veja abaixo quais dados são armazenados em cada tabela. agents idfirst_namelast_nameexperience_years 1KateWhite5 2MelissaBrown2 3AlexandrMcGregor3 4SophiaScott3 5StevenBlack1 6MariaScott1 customers idfirst_namelast_nameemail 11XavieraLopezxaviera111111@gmail.com 12GabrielCumberlygabriel111111@gmail.com 13ElisabethStevenselisabeth111111@gmail.com 14OprahWinfreyoprah111111@gmail.com 15IvanLeeivan111111@gmail.com sales idhouse_iddateagent_first_nameagent_last_namecustomer_idprice 10110122021-11-03KateWhite141200000 10221342021-12-06SophiaScott12950000 10310152021-12-10MariaScott13800000 10420132021-12-12AlexandrMcGregor151350000 10521122021-12-12AlexandrMcGregor151450000 10610102022-01-10StevenBlack111500000 Sem mais demora, vamos passar aos nossos exemplos. 1. Condição de Falta Os iniciantes não familiarizados com Cláusulas JOIN em SQL geralmente simplesmente listam as tabelas em FROM sem especificar a condição JOIN quando tentam combinar informações de duas ou mais tabelas. Esta é uma sintaxe válida, de modo que você não recebe nenhuma mensagem de erro. Mas o resultado é uma junção cruzada com todas as linhas de uma tabela combinada com todas as linhas de outra tabela. Por exemplo, suponha que queremos obter informações sobre o cliente que comprou uma determinada casa (ID nº 2134). Se utilizarmos a seguinte consulta: SELECT house_id, first_name, last_name, email FROM sales, customers WHERE house_id = 2134; Este é o resultado que obtemos: house_idfirst_namelast_nameemail 2134XavieraLopezxaviera111111@gmail.com 2134GabrielCumberlygabriel111111@gmail.com 2134ElisabethStevenselisabeth111111@gmail.com 2134OprahWinfreyoprah111111@gmail.com 2134IvanLeeivan111111@gmail.com Em vez de um registro com o cliente que queremos, temos todos os nossos clientes listados no conjunto de resultados. Para consertar a consulta, é necessária uma sintaxe explícita JOIN. As tabelas a serem combinadas estão especificadas em FROM e JOIN, e a condição de junção está especificada na cláusula ON: SELECT s.house_id, c.first_name, c.last_name, c.email FROM sales s JOIN customers c ON s.customer_id = c.id WHERE s.house_id = 2134; Aqui, nós especificamos o ID do cliente a partir do sales tabela para corresponder à identificação do cliente do customers mesa. Isto nos dá o resultado desejado: house_idfirst_namelast_nameemail 2134GabrielCumberlygabriel111111@gmail.com Você poderia especificar a condição de junção na cláusula WHERE para obter o mesmo resultado. Mas isso é contra o uso pretendido da cláusula WHERE. Além disso, há benefícios adicionais pelo uso da sintaxe JOIN em vez de listar as tabelas em FROM. Verifique este artigo para entender porque a sintaxe JOIN é a preferida. 2. Usando uma condição Incompleta ON Linhas indesejadas no conjunto de resultados podem vir de condições ON incompletas. Em alguns casos, você precisa unir tabelas por várias colunas. Nessas situações, se você usar apenas um par de colunas, isso resulta em linhas duplicadas. Digamos que queremos ver o nível de experiência do agente imobiliário para cada casa vendida. Se começarmos por nos juntar ao sales e agents tabelas com o sobrenome do agente: SELECT s.house_id, a.first_name, a.last_name, a.experience_years FROM sales s JOIN agents a ON s.agent_last_name = a.last_name ORDER BY s.house_id; isto é o que você obtém: house_idfirst_namelast_nameexperience_years 1010StevenBlack1 1012KateWhite5 1015MariaScott1 1015SophiaScott3 2013AlexandrMcGregor3 2112AlexandrMcGregor3 2134MariaScott1 2134SophiaScott3 Isso não funcionou bem. Temos dois agentes diferentes com o sobrenome Scott: Maria e Sophia. Como resultado, as casas #1015 e #2134 estão incluídas duas vezes cada uma com agentes diferentes. Para consertar esta consulta, precisamos nos unir ao sales e agents tabelas utilizando dois pares de colunas, correspondentes ao sobrenome e ao primeiro nome do agente: SELECT s.house_id, a.first_name, a.last_name, a.experience_years FROM sales s JOIN agents a ON s.agent_last_name = a.last_name AND s.agent_first_name = a.first_name ORDER BY s.house_id; E aqui está o resultado que estávamos procurando. house_idfirst_namelast_nameexperience_years 1010StevenBlack1 1012KateWhite5 1015MariaScott1 2013AlexandrMcGregor3 2112AlexandrMcGregor3 2134SophiaScott3 Embora JOIN seja uma das ferramentas básicas em SQL, você precisa estar ciente das muitas nuances diferentes para unir as tabelas de forma eficaz. Recomendo praticar Cláusulas JOIN em SQL com este curso interativo que cobre uma variedade de cenários de junção com 93 desafios de codificação. 3. Selecionando um sub-conjunto de colunas Em alguns casos, os registros no conjunto de resultados não são duplicados, mas aparecem como se fossem porque o subconjunto selecionado de colunas não mostra todas as diferenças entre os registros. Por exemplo, imagine que queremos ver as datas em que cada agente imobiliário vendeu uma casa. Se utilizarmos a seguinte consulta: SELECT a.first_name, a.last_name, s.date FROM agents a JOIN sales s ON s.agent_last_name = a.last_name AND s.agent_first_name = a.first_name; ela produz o seguinte resultado: first_namelast_namedate KateWhite2021-11-03 SophiaScott2021-12-06 AlexandrMcGregor2021-12-12 AlexandrMcGregor2021-12-12 MariaScott2021-12-10 StevenBlack2022-01-10 O conjunto de resultados inclui dois registros com Alexandr McGregor que parecem idênticos. Entretanto, se você adicionar a identificação da casa à declaração SELECT, você verá que estes dois registros correspondem à venda de duas casas diferentes no mesmo dia. Se você não estiver interessado nestas informações adicionais e quiser ter apenas uma fila exibida aqui, use DISTINCT: SELECT DISTINCT a.first_name, a.last_name, s.date FROM agents a JOIN sales s ON s.agent_last_name = a.last_name AND s.agent_first_name = a.first_name; Agora, o resultado é: first_namelast_namedate KateWhite2021-11-03 SophiaScott2021-12-06 AlexandrMcGregor2021-12-12 MariaScott2021-12-10 StevenBlack2022-01-10 4. Listando apenas as linhas de correspondência Um problema semelhante pode ocorrer se você quiser listar apenas as linhas de uma tabela, mas há vários registros correspondentes na outra tabela. Você acaba com duplicatas indesejadas em seu conjunto de resultados. Por exemplo, digamos que queremos listar todos os clientes que compraram casas através de nossa agência. Se utilizarmos a seguinte consulta: SELECT c.first_name, c.last_name, c.email FROM customers c JOIN sales s ON c.id = s.customer_id; aqui está o resultado: first_namelast_nameemail GabrielCumberlygabriel111111@gmail.com ElisabethStevenselisabeth111111@gmail.com XavieraLopezxaviera111111@gmail.com OprahWinfreyoprah111111@gmail.com IvanLeeivan111111@gmail.com IvanLeeivan111111@gmail.com Como você vê, a tabela resultante inclui Ivan Lee duas vezes. Isto porque ele comprou duas casas e há dois registros correspondentes na tabela sales mesa. Uma solução possível é usar DISTINCT, como no exemplo anterior. Uma solução ainda melhor é evitar o uso de SQL JOIN, filtrando o conjunto de resultados usando a palavra-chave EXISTS: SELECT c.first_name, c.last_name, c.email FROM customers c WHERE EXISTS (SELECT customer_id FROM sales); Agora, o resultado é: first_namelast_nameemail GabrielCumberlygabriel111111@gmail.com ElisabethStevenselisabeth111111@gmail.com XavieraLopezxaviera111111@gmail.com OprahWinfreyoprah111111@gmail.com IvanLeeivan111111@gmail.com Isto lhe dá o resultado desejado e também torna a intenção de sua consulta mais clara. 5. Usando a Auto-Adesão Finalmente, as duplicatas indesejadas em JOINs freqüentemente resultam de uma especificação incorreta das condições de união em auto-adesões - ou seja, quando uma mesa é unida a si mesma. Digamos que queremos que nossos agentes formem pares para nosso próximo treinamento. Obviamente, não queremos que nenhum agente seja emparelhado consigo mesmo. Portanto, podemos especificar a condição ON a1.id <> a2.id : SELECT a1.first_name as agent1_first_name, a1.last_name as agent1_last_name, a1.experience_years as agent1_experience, a2.first_name as agent2_first_name, a2.last_name as agent2_last_name, a2.experience_years as agent2_experience FROM agents a1 JOIN agents a2 ON a1.id <> a2.id ORDER BY a1.id; No entanto, esta consulta sai duas vezes a cada par. Por exemplo, na primeira linha da tabela abaixo, Kate White é considerada Agente 1, e Maria Scott é considerada Agente 2. Mas mais perto do final da tabela, obtém-se o mesmo par de agentes, mas com Maria Scott como Agente 1, e Kate White como Agente 2. agent1_first_nameagent1_last_nameagent1_experienceagent2_first_nameagent2_last_nameagent2_experience KateWhite5MariaScott1 KateWhite5StevenBlack1 KateWhite5MelissaBrown2 KateWhite5SophiaScott3 KateWhite5AlexandrMcGregor3 MelissaBrown2StevenBlack1 MelissaBrown2SophiaScott3 MelissaBrown2MariaScott1 MelissaBrown2AlexandrMcGregor3 MelissaBrown2KateWhite5 AlexandrMcGregor3MariaScott1 AlexandrMcGregor3MelissaBrown2 AlexandrMcGregor3SophiaScott3 AlexandrMcGregor3KateWhite5 AlexandrMcGregor3StevenBlack1 SophiaScott3MariaScott1 SophiaScott3StevenBlack1 SophiaScott3AlexandrMcGregor3 SophiaScott3MelissaBrown2 SophiaScott3KateWhite5 StevenBlack1SophiaScott3 StevenBlack1AlexandrMcGregor3 StevenBlack1MariaScott1 StevenBlack1MelissaBrown2 StevenBlack1KateWhite5 MariaScott1KateWhite5 MariaScott1AlexandrMcGregor3 MariaScott1SophiaScott3 MariaScott1StevenBlack1 MariaScott1MelissaBrown2 Para resolver este problema, você precisa acrescentar uma condição explícita para incluir cada par apenas uma vez. Uma solução comum é especificar a condição de união a1.id < a2.id. Com isto, você obtém o par Kate White e Maria Scott, mas não o contrário. Isto porque o ID da Kate (1) é um número inferior ao ID da Maria (6). Na prática, você pode ter algumas outras condições para a junção dos agentes. Por exemplo, você pode querer emparelhar agentes mais experientes (3+ anos) com agentes menos experientes (< 3 anos). A condição de filtragem correspondente em WHERE resolve o problema: SELECT a1.first_name as agent1_first_name, a1.last_name as agent1_last_name, a1.experience_years as agent1_experience, a2.first_name as agent2_first_name, a2.last_name as agent2_last_name, a2.experience_years as agent2_experience FROM agents a1 JOIN agents a2 ON a1.id <> a2.id WHERE a1.experience_years>=3 AND a2.experience_years < 3 ORDER BY a1.id; O resultado é o seguinte: agent1_first_nameagent1_last_nameagent1_experienceagent2_first_nameagent2_last_nameagent2_experience KateWhite5StevenBlack1 KateWhite5MelissaBrown2 KateWhite5MariaScott1 AlexandrMcGregor3MariaScott1 AlexandrMcGregor3StevenBlack1 AlexandrMcGregor3MelissaBrown2 SophiaScott3MariaScott1 SophiaScott3StevenBlack1 SophiaScott3MelissaBrown2 Este conjunto de resultados parece muito melhor e facilita a seleção de três pares, cada um consistindo de um agente com mais experiência e outro com menos experiência. Vamos praticar Cláusulas JOIN em SQL! Juntar tabelas em SQL não é tão difícil. Mas isso requer muita prática. Se você quiser evitar armadilhas como duplicatas indesejadas em JOINs e registros faltantes, siga este guia sobre como praticar Cláusulas JOIN em SQL. Se você tem apenas experiência básica com SQL e quer combinar dados de várias tabelas com mais confiança, eu recomendo isto Cláusulas JOIN em SQL curso interativo. Ele cobre todos os principais tipos de JOINs, bem como unir 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! Tags: sql aprender sql sql joins