如何在PostgreSQL中查找重复的logging

我有一个名为“user_links”的PostgreSQL数据库表,它目前允许下列重复字段:

year, user_id, sid, cid 

唯一的约束是目前第一个字段称为“ID”,但是我现在正在寻找添加一个约束,以确保yearuser_idsidcid都是唯一的,但我不能应用约束,因为重复值已经存在,这违反了这一点约束。

有没有办法find所有重复?

基本的想法是使用一个嵌套的查询与计数聚合:

 select * from yourTable ou where (select count(*) from yourTable inr where inr.sid = ou.sid) > 1 

您可以调整内部查询中的where子句以缩小search范围。


对于评论中提到的问题,还有一个很好的解决办法(但不是每个人都读它们):

 select Column1, Column2, count(*) from yourTable group by Column1, Column2 HAVING count(*) > 1 

或更短:

 SELECT (yourTable.*)::text, count(*) FROM yourTable GROUP BY yourTable.* HAVING count(*) > 1 

从“ 使用PostgreSQL查找重复行 ”这里是智能解决scheme:

 select * from ( SELECT id, ROW_NUMBER() OVER(PARTITION BY column1, column2 ORDER BY id asc) AS Row FROM tbl ) dups where dups.Row > 1 

您可以join到相同的表中将重复的字段,然后反对join的ID字段。 从第一个表别名(tn1)中selectid字段,然后在第二个表别名的id字段中使用array_agg函数。 最后,为了使array_agg函数正常工作,您将按tn1.id字段对结果进行分组。 这将产生一个结果集,其中包含一个logging的id和所有符合连接条件的id的数组。

 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; 

显然,id将在duplicate_entries数组中,对于一个id,在结果集中也会有自己的条目。 你将不得不使用这个结果集来决定你想要成为“真相”来源的那个id。 一个不应该被删除的logging。 也许你可以做这样的事情:

 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) 

select具有重复项的最小号码ID(假设ID正在增加int PK)。 这些将是您将保留的ID。