|

Encontrando duplicidade de registros em uma tabela do SQL Server

Compartilhe :

Em uma tabela muito grande, pode ser difícil localizar registros duplicados só de olhar. Neste artigo mostramos como encontrar essas duplicidades, como ver as linhas duplicadas completas (não só a contagem) e, ao final, como remover os duplicados com segurança.

A query básica: contando por campo(s)

SELECT cliente, COUNT(*) AS quantidade
FROM tbwebmundi
GROUP BY cliente
HAVING COUNT(*) > 1;

Como funciona:

  • O GROUP BY agrupa as linhas que têm o mesmo valor no campo analisado (aqui, cliente).
  • O COUNT(*) conta quantas linhas existem em cada grupo.
  • O HAVING COUNT(*) > 1 filtra e mostra apenas os grupos com mais de uma ocorrência — ou seja, os valores duplicados. Diferente do WHERE, o HAVING é aplicado depois do agrupamento, por isso é ele (e não o WHERE) que deve ser usado para filtrar com base em COUNT().

O ideal é que o campo analisado seja o que deveria funcionar como chave da tabela. Se não existir um único campo assim, é só incluir mais colunas no SELECT e no GROUP BY:

SELECT cliente, cpf, data_nascimento, COUNT(*) AS quantidade
FROM tbwebmundi
GROUP BY cliente, cpf, data_nascimento
HAVING COUNT(*) > 1;

Vendo as linhas duplicadas completas (não só a contagem)

A consulta acima mostra apenas os valores duplicados e a quantidade. Muitas vezes você precisa ver a linha inteira, com todos os campos, incluindo alguma coluna de identificação (como um id do tipo IDENTITY, mesmo que ele não faça parte da duplicidade em si). Para isso, use uma CTE com ROW_NUMBER():

WITH Duplicados AS (
    SELECT *,
           ROW_NUMBER() OVER (PARTITION BY cliente, cpf ORDER BY id) AS linha
    FROM tbwebmundi
)
SELECT *
FROM Duplicados
WHERE linha > 1;

Aqui, o PARTITION BY cria um “grupo” para cada combinação de cliente + cpf, e o ROW_NUMBER() numera as linhas dentro de cada grupo. Toda linha com número maior que 1 é uma duplicata da primeira ocorrência daquele grupo.

Removendo os duplicados, mantendo apenas um registro de cada

Depois de identificar as duplicatas, uma dúvida comum é como apagá-las mantendo só uma cópia de cada. A mesma CTE acima resolve isso — mas com bastante cuidado, pois a operação é destrutiva:

WITH Duplicados AS (
    SELECT *,
           ROW_NUMBER() OVER (PARTITION BY cliente, cpf ORDER BY id) AS linha
    FROM tbwebmundi
)
DELETE FROM Duplicados
WHERE linha > 1;

Recomendações antes de rodar um DELETE como esse:

  • Faça um backup da tabela (ou do banco) antes.
  • Rode primeiro a versão com SELECT (do tópico anterior) para conferir exatamente quais linhas seriam apagadas.
  • Se possível, teste em um ambiente de homologação antes de executar em produção.

Prevenindo duplicidades no futuro

Como já apontava a versão original deste artigo: o ideal é nunca precisar rodar essas consultas. Isso é resolvido criando uma chave primária ou um índice/constraint UNIQUE nos campos que não deveriam se repetir:

ALTER TABLE tbwebmundi
ADD CONSTRAINT UQ_Cliente_Cpf UNIQUE (cliente, cpf);

Com essa constraint em vigor, o próprio SQL Server passa a impedir a inserção de novos registros duplicados, eliminando o problema na origem.

Conclusão

GROUP BY + HAVING COUNT(*) > 1 é a forma clássica e eficaz de encontrar valores duplicados. Para ver as linhas completas ou removê-las mantendo apenas uma cópia, ROW_NUMBER() OVER (PARTITION BY ...) é a ferramenta certa. E, para evitar o problema de vez, vale a pena revisar se a tabela não deveria ter uma chave primária ou constraint UNIQUE nos campos relevantes.

Posts Similares