Podoba mi się rozwiązanie @erwin-brandstetter , ale chciałem pokazać rozwiązanie z USING
słowo kluczowe:
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;
Jeśli chcesz przejrzeć rekordy przed ich usunięciem, po prostu zastąp DELETE
z SELECT *
i USING
z przecinkiem ,
, czyli
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;
Aktualizacja:przetestowałem tutaj niektóre z różnych rozwiązań pod kątem szybkości. Jeśli nie spodziewasz się wielu duplikatów, to rozwiązanie działa znacznie lepiej niż te, które mają NOT IN (...)
klauzula, ponieważ generują one wiele wierszy w podzapytaniu.
Jeśli przepiszesz zapytanie, aby użyć IN (...)
wtedy działa podobnie do rozwiązania przedstawionego tutaj, ale kod SQL staje się znacznie mniej zwięzły.
Aktualizacja 2:Jeśli masz NULL
wartości w jednej z kluczowych kolumn (której naprawdę nie powinieneś używać IMO), możesz użyć COALESCE()
w warunku dla tej kolumny, np.
AND COALESCE(T1.col_with_nulls, '[NULL]') = COALESCE(T2.col_with_nulls, '[NULL]')