Ik vind de oplossing van @erwin-brandstetter leuk, maar wilde een oplossing laten zien met de USING
zoekwoord:
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;
Als u de records wilt bekijken voordat u ze verwijdert, vervangt u gewoon DELETE
met SELECT *
en USING
met een komma ,
, d.w.z.
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;
Update:ik heb hier enkele van de verschillende oplossingen getest op snelheid. Als je niet veel duplicaten verwacht, dan presteert deze oplossing veel beter dan die met een NOT IN (...)
clausule, aangezien deze veel rijen in de subquery genereren.
Als u de query herschrijft om IN (...)
. te gebruiken dan werkt het op dezelfde manier als de hier gepresenteerde oplossing, maar de SQL-code wordt veel minder beknopt.
Update 2:Als u NULL
. heeft waarden in een van de sleutelkolommen (wat je eigenlijk niet zou moeten IMO), dan kun je COALESCE()
gebruiken in de voorwaarde voor die kolom, bijvoorbeeld
AND COALESCE(T1.col_with_nulls, '[NULL]') = COALESCE(T2.col_with_nulls, '[NULL]')