仅删除相同产品ID的重复项

时间:2019-07-12 08:33:56

标签: sql postgresql duplicates sql-delete

表中包含产品的图像。每行都指向产品图像的URL。许多产品具有多个图像。

url > Image url
product_id > Product's ID

某些产品的图像重复。我只需要在重复项中保留一个,然后删除该产品的其他重复URL。

我无法对URL进行分组并删除重复项,因为可能会有另一行具有相同的URL并且具有不同的product_id。

TABLE
-
id | product_id | url | is_primary

enter image description here

2 个答案:

答案 0 :(得分:0)

根据要删除记录的方式,有几种不同的方法可以实现此目的。最直接的是:

SELECT
    DISTINCT ON (product_id)
          id
        , product_id
        , url
        , is_primary
FROM table

来自documentation

  

SELECT DISTINCT从结果中消除重复的行。 SELECT DISTINCT ON消除与所有指定表达式匹配的行。全选(默认)将返回所有候选行,包括重复项。 (请参见下面的DISTINCT条款。)

听起来您可能要使用DISTINCT ON而不是DISTINCT;区别在于DISTINCT ON使您可以返回不同组件的 not 部分的列。


如果您需要做一些更复杂的事情(例如,找到与id相关联的最小的product_id),则可以向查询中添加排序,这将通过添加ORDER BY子句来使结果具有确定性

与DISTINCT ON一起使用的ORDER BY子句要注意的是,DISTINCT ON中的所有列必须在ORDER BY中排在最前面。这样就可以找到与每个产品相关联的最小的id,例如:

SELECT
    DISTINCT ON (product_id)
          id
        , product_id
        , url
        , is_primary
FROM table
ORDER BY
      product_id
    , id ASC 

根据此表的设置方式,可能会有一个更简单的答案。如果is_primary是具有部分唯一索引的布尔列(有关更多详细信息,请参见this postthis documentation),则每个{{ 1}},查询如下:

id

之所以提及这一点,是因为这是一种非常好的筛选单个唯一值的方法,如果 这样设置数据库。根据表的大小,它的性能也可能更高,因为Postgres将在磁盘上有一个索引,并且不需要对所有可能的记录进行排序。


如果您的目标是实际上从表中删除重复的记录,那么一种方法是对有效记录进行查询(例如,上述之一),然后将其用作对表的USING子句带有WHERE NOT EXISTS子句的DELETE语句。

答案 1 :(得分:0)

您可以使用EXISTS删除重复项:

delete from tablename t
where exists (
  select 1 from tablename
  where product_id = t.product_id and url = t.url and id < t.id
)

这将仅是每个product_id的重复URL之一,其中id的URL最小。