Możesz dołączyć do tej samej tabeli na polach, które zostałyby zduplikowane, a następnie anty-dołączyć na polu id. Wybierz pole id z pierwszego aliasu tabeli (tn1), a następnie użyj funkcji array_agg w polu id drugiego aliasu tabeli. Wreszcie, aby funkcja array_agg działała poprawnie, wyniki zostaną pogrupowane według pola tn1.id. Spowoduje to wygenerowanie zestawu wyników zawierającego identyfikator rekordu i tablicę wszystkich identyfikatorów pasujących do warunków łączenia.
select tn1.id,
array_agg(tn2.id) as duplicate_entries,
from table_name tn1 join table_name tn2 on
tn1.year = tn2.year
and tn1.sid = tn2.sid
and tn1.user_id = tn2.user_id
and tn1.cid = tn2.cid
and tn1.id <> tn2.id
group by tn1.id;
Oczywiście identyfikatory, które będą w tablicy duplicate_entries dla jednego identyfikatora, również będą miały własne wpisy w zestawie wyników. Będziesz musiał użyć tego zestawu wyników, aby zdecydować, który identyfikator chcesz stać się źródłem „prawdy”. Jeden rekord, którego nie należy usuwać. Może mógłbyś zrobić coś takiego:
with dupe_set as (
select tn1.id,
array_agg(tn2.id) as duplicate_entries,
from table_name tn1 join table_name tn2 on
tn1.year = tn2.year
and tn1.sid = tn2.sid
and tn1.user_id = tn2.user_id
and tn1.cid = tn2.cid
and tn1.id <> tn2.id
group by tn1.id
order by tn1.id asc)
select ds.id from dupe_set ds where not exists
(select de from unnest(ds.duplicate_entries) as de where de < ds.id)
Wybiera najniższe numery identyfikatorów, które mają duplikaty (zakładając, że identyfikator zwiększa int PK). Byłyby to identyfikatory, które miałbyś przy sobie.