Jag gillar @erwin-brandstetters lösning, men ville visa en lösning med USING
nyckelord:
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;
Om du vill granska posterna innan du tar bort dem, ersätt bara DELETE
med SELECT *
och USING
med kommatecken ,
, 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;
Uppdatering:Jag testade några av de olika lösningarna här för hastighet. Om du inte förväntar dig många dubbletter fungerar den här lösningen mycket bättre än de som har en NOT IN (...)
sats eftersom de genererar många rader i underfrågan.
Om du skriver om frågan för att använda IN (...)
då fungerar den på samma sätt som lösningen som presenteras här, men SQL-koden blir mycket mindre koncis.
Uppdatering 2:Om du har NULL
värden i en av nyckelkolumnerna (som du egentligen inte borde IMO), då kan du använda COALESCE()
i villkoret för den kolumnen, t.ex.
AND COALESCE(T1.col_with_nulls, '[NULL]') = COALESCE(T2.col_with_nulls, '[NULL]')