2015-01-26 139 views
80

我有一個PostgreSQL數據庫的表稱爲「user_links」目前允許下列重複字段:如何找到重複記錄的PostgreSQL

year, user_id, sid, cid 

唯一性約束是目前所謂的「ID」的第一場,但是我我現在想要添加一個約束,以確保year,user_id, sidcid都是唯一的,但我無法應用該約束,因爲重複值已存在,違反了此約束。

有沒有辦法找到所有的重複?

+2

可能重複(http://stackoverflow.com/questions/14471179/find-duplicate-rows-with-postgresql ) – drs 2015-05-26 19:30:09

回答

125

的基本思想將使用嵌套查詢與數聚集:

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

可以在內部查詢調節where子句來縮小搜索範圍。


有針對在評論中提到的另一個很好的解決方案,(但不是每個人都讀):

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 
+25

你也可以使用HAVING:'select col1,col2,count(*)from tbl group by col1,col2 HAVING count(*)> 1' – alexkovelsky 2015-08-28 07:27:58

+0

感謝@alexkovelsky有聲明對我來說更容易修改並且運行更快。我會建議一個答案,以獲得更高的知名度。 – Vesanto 2016-03-14 15:58:25

+0

這些選項對我有用,其他人對結果進行分組,而這些選項給了我所有重複記錄,而不僅僅是重複記錄,謝謝! – rome3ro 2017-07-12 18:13:39

3

你可以加入到同一個表中的字段將被複制,然後反向加入id字段。從第一個表別名(tn1)中選擇id字段,然後在第二個表別名的id字段中使用array_agg函數。最後,爲了使array_agg函數正常工作,您將通過tn1.id字段對結果進行分組。這將生成一個結果集,其中包含一條記錄的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。一個不應該被刪除的記錄。也許你可以做這樣的事情:

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) 

選擇具有重複的最低數字ID(假設ID增加int PK)。這些將是您將保留的ID。

+0

嘗試添加你的代碼的解釋。 – ianaya89 2015-01-26 20:20:56

+0

@ ianaya89添加了解釋。 – pwnyexpress 2015-01-26 21:03:22

43

從 「Find duplicate rows with PostgreSQL」 這裏是聰明的解決辦法:在PostgreSQL查找重複的行]的

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

這是快!在幾秒鐘內完成數百萬行的工作。其他答案只是掛在那裏... – dmvianna 2016-03-04 06:50:26

+1

就像我看到的,這個查詢不考慮組內的所有行。它只顯示重複的東西,部分副本將與rownum = 1。糾正我如果我錯了 – 2016-05-24 08:33:43

+1

@vladimir Filipchenko要與所有行,添加一個級別Alexkovelsky解決方案: 'SELECT * FROM( SELECT * ,鉛(行,1)OVER()AS nextrow FROM( SELECT *, ROW_NUMBER()OVER(w)的AS 行FROM TBL 窗口W AS(PARTITION BY COL1,COL2 ORDER BY COL3) )× ) y WHERE row> 1 OR nextrow> 1;' – 2016-07-28 17:34:16