使用PostgreSQL查找重复的行


72

我们有一张带有以下各列的照片表:

id, merchant_id, url 

该表包含该组合的重复值merchant_id, url。因此一行可能会出现多次。

234 some_merchant  http://www.some-image-url.com/abscde1213
235 some_merchant  http://www.some-image-url.com/abscde1213
236 some_merchant  http://www.some-image-url.com/abscde1213

删除这些重复项的最佳方法是什么?(我使用PostgreSQL 9.2和Rails3。)


2
您的ID列是否唯一?我看到234 3次,但您说的是商人名和网址是重复的值。
sgeddes


1
对困惑感到抱歉。上面示例中的ID应该是唯一的。感谢您的正确编辑。这里的解决方案stackoverflow.com/questions/1746213/…对我的情况不起作用。
schlubbi 2013年

Answers:


126

这是我的看法。

select * from (
  SELECT id,
  ROW_NUMBER() OVER(PARTITION BY merchant_Id, url ORDER BY id asc) AS Row
  FROM Photos
) dups
where 
dups.Row > 1

通过定制要删除的记录以符合规范,可以随意处理订单。

SQL提琴=> http://sqlfiddle.com/#!15/d6941/1/0


不再支持Postgres 9.2的SQL Fiddle。将SQL Fiddle更新到Postgres 9.3


3
这就像一个符咒,但是如何删除使用此查询找到的重复项?
Trasplazio Garzuglio 2014年

如果我们有相同的事物重复3次,则结果为2和3。我该如何解决?
福斯托·卡瓦略·马克斯·席尔瓦

您正在尝试做什么还不清楚。提供的答案使用sql小提琴链接显示了如何根据定义的列删除行。您可能应该提出一个新的问题,其中包含要重现的特定步骤。
MatthewJ

您能解释一下它的实际作用 ROW_NUMBER() OVER(PARTITION BY merchant_Id, url ORDER BY id asc)

1
不,不是这样,这就是为什么要检查行> 1的原因。请参见sql小提琴。
MatthewJ

10

sgeddes的答案的第二部分不适用于Postgres(小提琴使用MySQL)。这是他使用Postgres的答案的更新版本:http ://sqlfiddle.com/#!12/ 6b1a7/1

DELETE FROM Photos AS P1  
USING Photos AS P2
WHERE P1.id > P2.id
   AND P1.merchant_id = P2.merchant_id  
   AND P1.url = P2.url;  

6

我为您提供了两种选择。

快速的操作方法如下:(假设您的ID列不是唯一的,因为您多次提到234次):

CREATE TABLE tmpPhotos AS SELECT DISTINCT * FROM Photos;
DROP TABLE Photos;
ALTER TABLE tmpPhotos RENAME TO Photos;

这是SQL Fiddle

如果有约束,则需要将约束添加回表中。

如果您的ID列是唯一的,则可以执行以下操作以保持最低ID:

DELETE FROM P1  
USING Photos P1, Photos P2
WHERE P1.id > P2.id
   AND P1.merchant_id = P2.merchant_id  
   AND P1.url = P2.url;  

小提琴


2
在我的情况下,该ID是唯一的。我在示例代码中做错了。但如果尝试使用第二种解决方案,则会收到错误消息。ERROR: relation "p1" does not exist
schlubbi 2013年

@StefanSchmidt我已修复它可以在Postgres而不是MySQL上运行:sqlfiddle.com/#
11101101b
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.