PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Como excluir linhas duplicadas sem identificador exclusivo


Eu gosto da solução do @erwin-brandstetter, mas queria mostrar uma solução com o USING palavra-chave:
DELETE   FROM table_with_dups T1
  USING       table_with_dups T2
WHERE  T1.ctid    < T2.ctid       -- delete the "older" ones
  AND  T1.name    = T2.name       -- list columns that define duplicates
  AND  T1.address = T2.address
  AND  T1.zipcode = T2.zipcode;

Se você quiser revisar os registros antes de excluí-los, basta substituir DELETE com SELECT * e USING com uma vírgula , , ou seja
SELECT * FROM table_with_dups T1
  ,           table_with_dups T2
WHERE  T1.ctid    < T2.ctid       -- select the "older" ones
  AND  T1.name    = T2.name       -- list columns that define duplicates
  AND  T1.address = T2.address
  AND  T1.zipcode = T2.zipcode;

Atualização:testei algumas das diferentes soluções aqui para velocidade. Se você não espera muitas duplicatas, então esta solução tem um desempenho muito melhor do que aquelas que têm um NOT IN (...) cláusula, pois geram muitas linhas na subconsulta.

Se você reescrever a consulta para usar IN (...) então ele tem um desempenho semelhante à solução apresentada aqui, mas o código SQL se torna muito menos conciso.

Atualização 2:se você tiver NULL valores em uma das colunas de chave (o que você realmente não deveria IMO), então você pode usar COALESCE() na condição para essa coluna, e.
  AND COALESCE(T1.col_with_nulls, '[NULL]') = COALESCE(T2.col_with_nulls, '[NULL]')