No entanto, é comum nos deparamos com bases de dados repletas de registros duplicados, o que pode ter ocorrido por conta de um mal planejamento ou, forçado devido a importação de dados externos.
Localizar e eliminar estes registros, será o que veremos neste artigo.
- Simulando Registros Duplicados
A forma mais simples de localizar os duplicados é através dos comandos GROUP BY e HAVING. Vamos popular uma tabela de produtos a fim de duplicar registros:
Create Table
produto ( id_produto
bigint not null
, descricao
varchar
(100), estoque
int not null default
0 ) ;
Insert Into
produto
Values
(1,
"Produto A"
, 10), (2,
"Produto B"
, 10), (3,
"Produto C"
, 10), (4,
"Produto B"
, 12), (5,
"Produto C"
, 8), (6,
"Produto D"
, 10), (7,
"Produto E"
, 10), (8,
"Produto E"
, 10), (9,
"Produto F"
, 10);
- Identificando os Duplicados
select
*
from
produto
group by
descricao
having
count
(descricao) > 1 ;
id_produto descricao estoque
---------- --------- -------
2 Produto B 10
3 Produto C 10
7 Produto E 10
Localizar os registros foi possível pois, agrupamos os diferentes produtos em um só (group by), após, adicionamos a condição para que somente os registros que contenham mais de uma ocorrência (having...) fossem apresentados. (Mais de uma ocorrência após agrupado). No exemplo, filtramos somente os registros com mais de uma ocorrência, mas você pode especificar a quantidade desejada.[Dica]
Observe que os registros encontrados como duplicados foram os com menor id.
Além de lista-los, podemos identificar todos eles e, saber quantas vezes cada um está repetido, vejamos:
select
descricao,
count
(descricao)
as
Quantidade
from
produto
group by
descricao
having
count
(descricao) > 1 ;
descricao Quantidade
--------- ----------
Produto B 2
Produto C 2
Produto E 2
Com o count, agora sabemos que para cada registro duplicado, existem duas linhas em nossa tabela.Agora que já sabemos como identificar os registros, como excluí-los?
- Excluindo os Duplicados
Antes de excluir os registros, é importante saber se eles não são chaves estrangeiras em outras tabelas, o que pode causar um grande estrago em seu banco de dados se o relacionamento foi criado com on delete cascade.
Precauções a parte, vamos excluir os registros. Podemos fazer isso de várias formas, focarei somente na forma mais prática e usual que aplico:
1º - Crio uma tabela com os registros duplicados, esta tabela pode ser apagada posteriormente, no entanto, recomendo não fazer isso, pois, ela pode ser usada posteriormente para fins de consulta:
Não entendeu a forma que criei a tabela? Leia esta matéria que entenderá: Criando uma tabela com base em outra já existente.
create table
produto_duplicado (
select
*
from
produto
group by
descricao
having
count
(descricao) > 1) ;
Lembra da dica que dei acima? Então, neste momento você pode optar por excluir os registros mais antigos, ou mais recentes, no caso, se preferir manter os mais antigos, coloque um max na coluna id_produto.
2º - Com a tabela criada, excluiremos os registros:
Nenhum segredo na linha do delete, o x da questão está na tabela que criamos, usamos ela em um sub-select, desta forma, apagamos somente os registros duplicados.
delete
from
produto
where
produto.id_produto
in
(
select
produto_duplicado.id_produto
from
produto_duplicado
where
produto_duplicado.id_produto = produto.id_produto) ;
Caso tenha ficado alguma dúvida, queira dar uma sugestão ou reclamar também (:d), poste nos comentários, terei o maior prazer em responder, um grande abraço.
- Perguntas Frequentes
Você menciona que existem outras formas de excluir os registros, quais?
- http://www.devmedia.com.br/forum/como-retornar-e-excluir-registros-duplicados-via-select/32873
- http://msmvps.com/blogs/cmattos/archive/2011/05/07/sql-como-excluir-registros-duplicados-numa-tabela-sem-chave-prim-225-ria.aspx
- http://gustavomaiaaguiar.wordpress.com/2009/05/30/como-eliminar-linhas-duplicadas-e-repeticoes-no-sql-server/
- http://ericsilva.wordpress.com/2013/07/11/como-excluir-registros-duplicados-no-mysql/
http://magaweb.com.br/blog/?p=450
No seu caso, existem apenas dois registros duplicados para cada produto, se houvessem mais, como eu faria para manter somente um?
Crie uma tabela com os registros que serão mantidos (vide exemplo no 4º link da primeira pergunta), após, apague os registros com o delete apresentado acima (Adaptações poderão ser necessárias).
Olá, eu também uso (dentre outros bancos de dados) o SQL Server. Eu o uso muito para tratar dados em processos de migração de sistemas – clientes que mudam seus programas para outro fornecedor; o SQL Server é perfeito pra mim. Essa questão de linhas duplicadas é uma pegadinha, especialmente porque cada situação traz um cenário particular. Acabei de resolver um problema que estava me “torrando o juízo”: precisei juntar duas tabelas com UNION em uma terceira tabela, onde criei um campo “chave” do tipo IDENTITY (autonumeração ou sequencial do SQL Server), já que eu tinha “id’s” repetidos para os mesmos clientes/fornecedores, no entanto, teria que eliminar as duplicidades mesmo assim. Observando bem, vi que poderia usar duas colunas como critério de desempate: o nome e o CNPJ, e eis o script que usei pra resolver este problema:
ResponderExcluirdelete from pessoa where chave in (select dup.chave from
(select nome, cpf_cnpj, max(chave) as chave, COUNT(*) as contador from pessoa
group by nome, cpf_cnpj
having COUNT(*) > 1) dup)
Espero poder ajudar a outros com o mesmo problema.
DEIXE UM COMENTÁRIO
Ao usar o seguinte comando:
ResponderExcluircreate table produto_duplicado
(select
*
from
produto
group by descricao
having count(descricao) > 1) ;
ELE ME RETORNA A SEGUINTE MENSAGEM:
ERRO: erro de sintaxe em ou próximo a "select"
LINE 2: (select
^
********** Error **********
ERRO: erro de sintaxe em ou próximo a "select"
SQL state: 42601
Character: 39
Podes me ajudar? agradeçop
select * INTO DUPLICADA
ResponderExcluirfrom
produto
group by descricao
having count(descricao) > 1) ;