sexta-feira, 17 de junho de 2016

Excluindo registros repetidos


No link https://support.microsoft.com/pt-br/kb/139444 onde a Microsoft mostra como eliminar duplicidades de tuplas, podemos acrescentar outra técnica bem conhecida no exemplo, usando a própria t1. A técnica da holdkey table onde se exclui todos os registros e depois precisa reincluir pode não ser a opção ideal em bancos muito grandes, com uma tabela cheia de chaves, constraints, triggers, identity, etc.

Há uma solução padrão que usamos sem precisar reinserir os códigos distinct, pois a exclusão é feita sem precisar remover as multiplicidades, mas somente excluindo as n-1 ocorrências. O requisito é ter uma coluna que seja pelo menos uma chave candidata para fazer a exclusão da linha que não será eliminada.

ALTER TABLE t1 ADD id_1 int identity(1,1) not null;  --Criando a chave candidata, já que t1 não tem uma, e que pode ser temporária apenas para a exclusão

delete t1
where
    col2 in (SELECT col2 FROM t1 GROUP BY col2 HAVING count(*) > 1)
    and NOT id_1 in (SELECT MIN(ID_1) FROM t1 GROUP BY col2 HAVING count(*) > 1)

Em caso de múltiplas colunas, onde a cláusula IN não permite mais que uma coluna***, podemos concatenar

Exemplo real, utilizado recentemente em um cliente:
delete from dias_leitura
where codigo_cliente+cast(subcodigo as varchar) in
  (select codigo_cliente+cast(subcodigo as varchar) from dias_leitura
   group by codigo_cliente + cast(subcodigo as varchar)
   having Count(*)>1)
and not codigo in
  (select Min(codigo) from dias_leitura
   group by  codigo_cliente+cast(subcodigo as varchar)
   having Count(*)>1)

*** Isto é permitido no Oracle:  WHERE col1, col2 in (select col1, col2 from t1)...