Encontrar registros duplicados em SQL pode ser uma tarefa tediosa, mas é uma habilidade essencial para quem trabalha com bancos de dados. Duplicatas podem causar erros, discrepâncias e inconsistências nos seus dados, levando a resultados incorretos e desempenho ruim. Por isso, é crucial identificar e remover duplicatas das suas tabelas para garantir a integridade e precisão dos dados.
O SQL oferece várias maneiras de encontrar duplicatas nos seus dados, dependendo das suas necessidades e da estrutura das suas tabelas. Você pode usar as cláusulas GROUP BY e HAVING para agrupar registros por uma coluna específica e filtrar duplicatas com base em uma contagem ou condição. Alternativamente, você pode usar a palavra-chave DISTINCT para selecionar apenas valores únicos e compará-los com a tabela original para identificar duplicatas. Existem também funções e operadores especializados, como COUNT(), EXISTS e JOIN, que podem ajudá-lo a encontrar duplicatas em cenários mais complexos.
Ao longo deste guia, você encontrará exercícios SQL interativos que permitem praticar a busca por duplicatas diretamente no navegador — sem necessidade de configurar um banco de dados. Escreva consultas, receba feedback instantâneo e veja se seus resultados correspondem à saída esperada.
Neste artigo, exploraremos várias técnicas para encontrar duplicatas em SQL, desde consultas simples até métodos avançados, e forneceremos exemplos e boas práticas para ajudá-lo a dominar essa habilidade. Seja você iniciante ou desenvolvedor SQL experiente, este guia ajudará a melhorar a qualidade e eficiência dos seus dados, detectando e eliminando duplicatas das suas tabelas. Para praticar essas consultas, considere usar um editor SQL moderno como o editor SQL do Beekeeper Studio, que oferece destaque de sintaxe e recursos de autocompletar.
Encontrando Duplicatas Usando as Cláusulas GROUP BY e HAVING
Uma maneira de encontrar valores duplicados em SQL é usando as cláusulas GROUP BY e HAVING. Essas cláusulas permitem agrupar linhas que têm os mesmos valores em uma ou mais colunas e, em seguida, filtrar os grupos com base em certos critérios. Veja como funciona:
- Comece selecionando as colunas que você deseja verificar por duplicatas usando a instrução SELECT.
- Use a cláusula GROUP BY para agrupar as linhas pelas colunas selecionadas.
- Use a função COUNT na cláusula HAVING para filtrar os grupos que têm mais de uma linha. Esses são os grupos que contêm duplicatas.
Por exemplo, digamos que você tenha uma tabela chamada “customers” com colunas para “name” e “email”. Você quer encontrar todos os clientes que se registraram com o mesmo endereço de email. Veja como seria a consulta SQL:
SELECT name, email, COUNT(*)
FROM customers
GROUP BY email
HAVING COUNT(*) > 1;
Esta consulta agrupa os clientes pelos seus endereços de email e depois conta o número de clientes em cada grupo. A cláusula HAVING filtra os grupos que têm apenas um cliente, deixando apenas os grupos com endereços de email duplicados.
Pratique você mesmo:
[[ testData.title ]]
Consulte a tabela users para encontrar todos os endereços de email que aparecem mais de uma vez. Retorne o email e o count de quantas vezes cada email duplicado aparece.
[[ col ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.your_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.expected_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ error ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ testData.solution ]]
Tabelas Disponíveis
[[ table.name ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
É importante notar que a cláusula GROUP BY deve incluir todas as colunas que você está selecionando, exceto aquelas que usam uma função agregada como COUNT. Caso contrário, a consulta retornará um erro.
Outro ponto a ter em mente é que a função COUNT conta todas as linhas em cada grupo, não apenas as únicas. Então, se você tiver várias linhas com o mesmo nome e endereço de email, todas serão contadas como duplicatas.
Além de usar as cláusulas GROUP BY e HAVING, você também pode usar outras instruções SQL como ORDER BY, WHERE e JOIN para refinar ainda mais sua busca por duplicatas. Você também pode usar restrições únicas para evitar que valores duplicados sejam inseridos em uma tabela em primeiro lugar.
No geral, encontrar duplicatas em SQL pode ser uma ferramenta poderosa para limpar dados não tratados ou identificar possíveis erros humanos ou bugs de aplicação. Usando os critérios de busca corretos e apresentando os resultados de forma clara e concisa, você pode identificar rapidamente linhas ou valores duplicados e tomar medidas para corrigi-los.
Usando a Função COUNT
Uma maneira de encontrar duplicatas em SQL é usando a função COUNT. A função COUNT é uma função agregada que conta o número de linhas em uma tabela que atendem a uma determinada condição. Usando a função COUNT, você pode contar o número de ocorrências de um valor específico em uma coluna e identificar duplicatas.
Para usar a função COUNT para encontrar duplicatas, você precisará agrupar as linhas pela coluna que deseja verificar por duplicatas. A cláusula GROUP BY é usada para agrupar as linhas com base nos valores em uma coluna específica. Por exemplo, se você quiser encontrar duplicatas na coluna “email” de uma tabela “users”, você agruparia as linhas pela coluna “email”.
Aqui está um exemplo de consulta que usa a função COUNT para encontrar duplicatas na coluna “email” de uma tabela “users”:
SELECT email, COUNT(email) as count
FROM users
GROUP BY email
HAVING COUNT(email) > 1;
Nesta consulta, a cláusula GROUP BY agrupa as linhas pela coluna “email”, e a função COUNT conta o número de ocorrências de cada endereço de email. A cláusula HAVING filtra os resultados para mostrar apenas os endereços de email que têm mais de uma ocorrência.
O resultado desta consulta será uma tabela que mostra os endereços de email que têm duplicatas e o número de ocorrências de cada endereço de email. Você pode usar esta informação para identificar e remover as linhas duplicadas da tabela.
Usar a função COUNT é uma maneira simples e eficaz de encontrar duplicatas em SQL. Ela permite identificar rapidamente os valores duplicados em uma coluna e tomar medidas para removê-los da tabela.
Usando a Cláusula INNER JOIN
Uma das maneiras mais comuns de encontrar duplicatas em SQL é usando a cláusula INNER JOIN. Esta cláusula permite combinar duas ou mais tabelas com base em uma coluna comum e retornar apenas as linhas que têm valores correspondentes em ambas as tabelas.
Para usar a cláusula INNER JOIN para encontrar duplicatas, você precisará identificar as colunas que contêm os dados duplicados. Uma vez que tenha identificado essas colunas, você pode usar a cláusula INNER JOIN para juntar a tabela nessas colunas.
Aqui está um exemplo de como usar a cláusula INNER JOIN para encontrar duplicatas em uma tabela chamada “orders”:
SELECT o1.order_id, o2.order_id
FROM orders o1
INNER JOIN orders o2
ON o1.customer_id = o2.customer_id
AND o1.order_date = o2.order_date
AND o1.order_id <> o2.order_id;
Neste exemplo, a cláusula INNER JOIN é usada para juntar a tabela “orders” consigo mesma, usando as colunas “customer_id” e “order_date” como critérios de junção. O operador “AND” é usado para especificar que todas as três colunas devem corresponder para que uma linha seja retornada. A linha final da consulta, “AND o1.order_id <> o2.order_id”, garante que a consulta não retorne linhas onde ambos os valores de “order_id” sejam iguais.
O resultado desta consulta será uma lista de todos os pedidos que têm o mesmo ID de cliente e data do pedido, mas IDs de pedido diferentes. Esses são os pedidos duplicados que precisam ser investigados mais a fundo.
Pratique com self-joins:
[[ testData.title ]]
Consulte a tabela products para encontrar todos os registros de produtos duplicados (mesmo product_name e category). Retorne o product_id, product_name, category e price apenas dos registros duplicados (não a primeira ocorrência).
[[ col ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.your_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.expected_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ error ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ testData.solution ]]
Tabelas Disponíveis
[[ table.name ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
Usar a cláusula INNER JOIN desta forma pode ser uma ferramenta poderosa para encontrar duplicatas em SQL. No entanto, é importante ter cuidado ao usar este método, pois pode ser fácil retornar acidentalmente falsos positivos ou perder duplicatas que estão espalhadas em várias tabelas. É sempre uma boa ideia verificar novamente seus resultados e usar outros métodos, como cláusulas GROUP BY e HAVING, para confirmar suas descobertas.
Pratique você mesmo:
[[ testData.title ]]
Consulte a tabela customers para retornar os registros completos dos clientes (name e email) cujo email aparece mais de uma vez. Use uma subconsulta para identificar emails duplicados.
[[ col ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.your_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.expected_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ error ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ testData.solution ]]
Tabelas Disponíveis
[[ table.name ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
Encontrando Pares Duplicados Usando Self-Joins
Outra técnica poderosa para encontrar duplicatas é usar self-joins para identificar pares de registros que compartilham características comuns. Esta abordagem é particularmente útil quando você quer encontrar pares duplicados exatos em vez de apenas identificar que duplicatas existem.
Um self-join envolve juntar uma tabela consigo mesma usando aliases diferentes. Ao juntar nas colunas que definem duplicatas e garantir que você não combine um registro consigo mesmo, você pode identificar pares duplicados de forma eficaz.
Por exemplo, se você tem uma tabela de transações e quer encontrar pares de transações com o mesmo ID de cliente e valor, mas IDs de transação diferentes, você pode usar um self-join assim:
SELECT t1.transaction_id as transaction_id1,
t2.transaction_id as transaction_id2,
t1.customer_id,
t1.amount
FROM transactions t1
INNER JOIN transactions t2
ON t1.customer_id = t2.customer_id
AND t1.amount = t2.amount
AND t1.transaction_id < t2.transaction_id;
Os pontos-chave nesta consulta são:
-
t1et2são aliases para a mesma tabela - As condições de junção especificam o que torna os registros “duplicados” (
customer_ideamount) -
t1.transaction_id < t2.transaction_idgarante que obtemos cada par apenas uma vez e não combinamos um registro consigo mesmo
Pratique você mesmo:
[[ testData.title ]]
Consulte a tabela transactions para encontrar pares de transações que têm o mesmo customer_id e amount, mas diferentes transaction_id. Retorne transaction_id1, transaction_id2, customer_id e amount para cada par duplicado. Mostre cada par apenas uma vez (evite mostrar tanto A-B quanto B-A).
[[ col ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.your_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.expected_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ error ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ testData.solution ]]
Tabelas Disponíveis
[[ table.name ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
Encontrando Duplicatas Usando Common Table Expressions (CTE)
Uma das maneiras de encontrar duplicatas em SQL é usando Common Table Expressions (CTE). Uma CTE é um conjunto de resultados temporário que é definido dentro do escopo de execução de uma única instrução SELECT, INSERT, UPDATE, DELETE ou CREATE VIEW.
Para encontrar duplicatas usando CTE, pode-se usar a função ROW_NUMBER(), que atribui um número sequencial único a cada linha dentro de uma partição de um conjunto de resultados. A cláusula PARTITION BY especifica as colunas usadas para definir a partição, e a cláusula ORDER BY especifica a ordem das linhas dentro de cada partição.
Aqui está um exemplo de uso de CTE para encontrar duplicatas:
WITH CTE AS (
SELECT column1, column2, column3, ROW_NUMBER() OVER(PARTITION BY column1, column2, column3 ORDER BY column1, column2, column3) AS RowNumber
FROM table_name
)
SELECT *
FROM CTE
WHERE RowNumber > 1
Neste exemplo, a CTE é definida com as colunas a serem verificadas por duplicatas. A função ROW_NUMBER() é usada para gerar um número de sequência para cada linha dentro de uma partição do conjunto de resultados, onde a partição é definida pelas colunas especificadas na cláusula PARTITION BY. O conjunto de resultados é então filtrado para mostrar apenas linhas onde o RowNumber é maior que 1, indicando que há duplicatas.
É importante notar que a cláusula ORDER BY dentro da função ROW_NUMBER() deve corresponder à cláusula ORDER BY na instrução SELECT principal, caso contrário os resultados podem não ser precisos.
Usar CTE para encontrar duplicatas pode ser especialmente útil no SQL Server 2017, que introduziu suporte para processamento de grafos usando Common Table Expressions. Isso permite consultas mais complexas envolvendo relacionamentos entre dados.
No geral, usar CTE para encontrar duplicatas em SQL pode ser uma ferramenta poderosa para análise e gerenciamento de dados.
Pratique você mesmo:
[[ testData.title ]]
Consulte a tabela products usando uma Common Table Expression (CTE) para encontrar nomes de produtos duplicados. A CTE deve agrupar por nome do produto e contar ocorrências, depois selecionar produtos com contagem > 1.
[[ col ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.your_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.expected_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ error ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ testData.solution ]]
Tabelas Disponíveis
[[ table.name ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
Encontrando Duplicatas Usando Funções de Janela
Quando se trata de encontrar duplicatas em SQL, uma das maneiras mais eficientes é usando funções de janela. Funções de janela são uma ferramenta poderosa que pode ser usada para realizar cálculos em um conjunto de linhas que estão relacionadas à linha atual.
Para encontrar duplicatas usando funções de janela, você pode usar a função ROW_NUMBER() em combinação com uma cláusula PARTITION BY. A função ROW_NUMBER() atribui um número único a cada linha dentro de uma partição, e a cláusula PARTITION BY agrupa linhas em partições com base em uma coluna específica ou conjunto de colunas.
Por exemplo, suponha que você tenha uma tabela de usuários que inclui colunas para user_id, username e email. Para encontrar todos os usuários que têm emails duplicados, você pode usar a seguinte instrução select:
SELECT user_id, username, email
FROM (
SELECT user_id, username, email,
ROW_NUMBER() OVER (PARTITION BY email ORDER BY user_id) AS row_num
FROM users
) AS subquery
WHERE row_num > 1;
Neste exemplo, a cláusula PARTITION BY particiona as linhas pela coluna email, e a função ROW_NUMBER() atribui um número único a cada linha dentro da partição com base na coluna user_id. A cláusula WHERE filtra todas as linhas exceto aquelas com um row_num maior que 1, que são as linhas com emails duplicados.
Pratique com ROW_NUMBER():
[[ testData.title ]]
Consulte a tabela customers para retornar os registros completos dos clientes (name e email) cujo email aparece mais de uma vez. Use uma subconsulta para identificar emails duplicados.
[[ col ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.your_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.expected_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ error ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ testData.solution ]]
Tabelas Disponíveis
[[ table.name ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
É importante notar que funções de janela podem ser usadas em combinação com outras funções SQL, como instruções CASE e funções agregadas, para criar consultas mais complexas. Por exemplo, você poderia usar uma instrução CASE para agrupar linhas em uma categoria específica e, em seguida, usar uma função de janela para encontrar duplicatas dentro dessa categoria.
Em conclusão, usar funções de janela para encontrar duplicatas em SQL pode ser um método poderoso e eficiente. Ao usar a função ROW_NUMBER() em combinação com uma cláusula PARTITION BY, você pode facilmente agrupar linhas em partições e atribuir números únicos a cada linha dentro da partição. Isso permite identificar e remover rapidamente linhas duplicadas dos seus resultados.
Pratique você mesmo:
[[ testData.title ]]
Consulte a tabela products para encontrar todos os registros de produtos duplicados (mesmo product_name e category). Retorne o product_id, product_name, category e price apenas dos registros duplicados (não a primeira ocorrência).
[[ col ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.your_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ i18n.expected_results ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ error ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ testData.solution ]]
Tabelas Disponíveis
[[ table.name ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
Usando a Função ROW_NUMBER() com Cláusula PARTITION BY
Ao pesquisar por duplicatas em um banco de dados SQL, uma ferramenta útil é a função ROW_NUMBER() com a cláusula PARTITION BY. Esta função atribui um número único a cada linha em um conjunto de resultados, com base nos critérios de particionamento especificados.
A cláusula PARTITION BY permite ao usuário agrupar as linhas em partições com base em uma ou mais colunas. Isso significa que a função ROW_NUMBER() atribuirá um número único a cada linha dentro de cada partição, em vez de em todo o conjunto de resultados.
Por exemplo, considere uma tabela de pedidos de clientes com colunas para ID do pedido, ID do cliente e data do pedido. Para encontrar pedidos duplicados para cada cliente, pode-se usar a seguinte consulta:
SELECT order_id, customer_id, order_date,
ROW_NUMBER() OVER (PARTITION BY customer_id, order_date
ORDER BY order_id) AS row_num
FROM orders
Nesta consulta, a função ROW_NUMBER() é usada com a cláusula PARTITION BY para agrupar os pedidos por cliente e data do pedido. A função então atribui um número único a cada linha dentro de cada partição, com base no ID do pedido.
A tabela resultante terá uma coluna adicional chamada “row_num” que contém os números de linha atribuídos. Duplicatas podem então ser identificadas selecionando linhas com row_num maior que 1.
Usar a função ROW_NUMBER() com a cláusula PARTITION BY pode ser uma ferramenta poderosa para encontrar duplicatas em bancos de dados SQL. Ao agrupar as linhas em partições com base em critérios específicos, a função pode atribuir números únicos a cada linha dentro de cada partição, facilitando a identificação de duplicatas.
Usando Instrução CASE com Função ROW_NUMBER()
Em SQL, a função ROW_NUMBER() é usada para atribuir um número sequencial único a cada linha em um conjunto de resultados. Esta função pode ser usada em conjunto com a instrução CASE para identificar registros duplicados em uma tabela.
A instrução CASE permite que lógica condicional seja aplicada a cada linha em um conjunto de resultados. Ao utilizar a função ROW_NUMBER() dentro da instrução CASE, o número de ocorrências de cada registro pode ser determinado.
Por exemplo, a seguinte consulta SQL pode ser usada para encontrar registros duplicados em uma tabela “users” com base nas colunas “first_name” e “last_name”:
SELECT *,
CASE
WHEN ROW_NUMBER() OVER (PARTITION BY first_name, last_name ORDER BY id) > 1
THEN 'Duplicado'
ELSE 'Único'
END AS duplicate_status
FROM users;
A consulta acima particiona o conjunto de resultados pelas colunas “first_name” e “last_name” e ordena as linhas pela coluna “id”. A função ROW_NUMBER() atribui um número sequencial único a cada linha dentro de cada partição.
A instrução CASE então verifica se o valor ROW_NUMBER() é maior que 1. Se for, então a linha é identificada como duplicada. Se não, a linha é identificada como única.
O conjunto de resultados incluirá uma coluna adicional chamada “duplicate_status” que exibe “Duplicado” ou “Único” para cada linha.
| id | first_name | last_name | duplicate_status | |
|---|---|---|---|---|
| 1 | John | Smith | john@example.com | Único |
| 2 | Jane | Doe | jane@example.com | Único |
| 3 | John | Smith | john.smith@example.com | Duplicado |
| 4 | Bob | Johnson | bob@example.com | Único |
| 5 | Jane | Doe | jane.doe@example.com | Duplicado |
No exemplo acima, as linhas 1, 2 e 4 são identificadas como únicas, enquanto as linhas 3 e 5 são identificadas como duplicadas com base nas colunas “first_name” e “last_name”.
Ao utilizar a função ROW_NUMBER() dentro da instrução CASE, registros duplicados podem ser facilmente identificados e gerenciados em uma tabela SQL.
Beekeeper Studio É Uma GUI de Banco de Dados Gratuita e de Código Aberto
A melhor ferramenta de consultas SQL e editor que já usei. Fornece tudo que preciso para gerenciar meu banco de dados. - ⭐⭐⭐⭐⭐ Mit
Beekeeper Studio é rápido, intuitivo e fácil de usar. Beekeeper suporta muitos bancos de dados e funciona muito bem no Windows, Mac e Linux.
O Que Os Usuários Dizem Sobre o Beekeeper Studio
"O Beekeeper Studio substituiu completamente meu antigo fluxo de trabalho com SQL. É rápido, intuitivo e torna o trabalho com banco de dados agradável novamente."
"Já experimentei muitas GUIs de banco de dados, mas o Beekeeper encontra o equilíbrio perfeito entre recursos e simplicidade. Simplesmente funciona."