Jeg kan godt lide @erwin-brandstetters løsning, men ville gerne vise en løsning med USING
søgeord:
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;
Hvis du vil gennemgå posterne, før du sletter dem, skal du blot erstatte DELETE
med SELECT *
og USING
med et komma ,
, dvs.
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;
Opdatering:Jeg testede nogle af de forskellige løsninger her for hastighed. Hvis du ikke forventer mange dubletter, så yder denne løsning meget bedre end dem, der har en NOT IN (...)
klausul, da disse genererer mange rækker i underforespørgslen.
Hvis du omskriver forespørgslen til at bruge IN (...)
så fungerer den på samme måde som den her præsenterede løsning, men SQL-koden bliver meget mindre kortfattet.
Opdatering 2:Hvis du har NULL
værdier i en af nøglekolonnerne (som du egentlig ikke burde IMO), så kan du bruge COALESCE()
i tilstanden for den kolonne, f.eks.
AND COALESCE(T1.col_with_nulls, '[NULL]') = COALESCE(T2.col_with_nulls, '[NULL]')