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]')