仅删除相同产品 ID 的重复项
Remove duplicates for the same product id only
Table 保存产品的图像。每行指向产品图像的 URL。许多产品有多个图像。
url > Image url
product_id > Product's ID
有些产品有重复的图片。我只需要从重复项中保留一个并删除该产品的其他重复项 URL。
我无法对 URL 进行分组并删除重复项,因为可能有另一行具有相同的 URL 和不同的 product_id。
TABLE
-
id | product_id | url | is_primary
根据您希望de-duplicate记录的方式,有几种不同的方法可以完成此操作。最直接的是:
SELECT
DISTINCT ON (product_id)
id
, product_id
, url
, is_primary
FROM table
SELECT DISTINCT eliminates duplicate rows from the result. SELECT DISTINCT ON eliminates rows that match on all the specified expressions. SELECT ALL (the default) will return all candidate rows, including duplicates. (See DISTINCT Clause below.)
听起来您可能想要使用 DISTINCT ON 而不是 DISTINCT;不同之处在于 DISTINCT ON 允许您 return 列 而不是 不同组件的一部分。
如果您需要做一些更复杂的事情(例如,找到与 product_id
关联的最小 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
根据 table 的设置方式,可能会有更简单的答案。如果 is_primary
是具有部分唯一索引的布尔列(请参阅 this post and this documentation 了解更多详细信息),您将能够通过查询获得每个 product_id
的单个 id
喜欢:
SELECT
id
, product_id
, url
, is_primary
FROM table
WHERE is_primary
我之所以提到这一点,是因为如果您的数据库是以这种方式设置的,那么它是过滤到单个唯一值的非常好的方法。根据您的 table 大小,它也可能更高效,因为 Postgres 将在磁盘上有一个索引并且不需要对所有可能的记录进行排序。
如果您的目标是实际删除 table 中的重复记录,一种方法是使用有效记录形成查询(例如上述之一),然后使用它作为带有 WHERE NOT EXISTS 子句的 DELETE 语句的 USING 子句。
您可以使用 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
。
Table 保存产品的图像。每行指向产品图像的 URL。许多产品有多个图像。
url > Image url
product_id > Product's ID
有些产品有重复的图片。我只需要从重复项中保留一个并删除该产品的其他重复项 URL。
我无法对 URL 进行分组并删除重复项,因为可能有另一行具有相同的 URL 和不同的 product_id。
TABLE
-
id | product_id | url | is_primary
根据您希望de-duplicate记录的方式,有几种不同的方法可以完成此操作。最直接的是:
SELECT
DISTINCT ON (product_id)
id
, product_id
, url
, is_primary
FROM table
SELECT DISTINCT eliminates duplicate rows from the result. SELECT DISTINCT ON eliminates rows that match on all the specified expressions. SELECT ALL (the default) will return all candidate rows, including duplicates. (See DISTINCT Clause below.)
听起来您可能想要使用 DISTINCT ON 而不是 DISTINCT;不同之处在于 DISTINCT ON 允许您 return 列 而不是 不同组件的一部分。
如果您需要做一些更复杂的事情(例如,找到与 product_id
关联的最小 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
根据 table 的设置方式,可能会有更简单的答案。如果 is_primary
是具有部分唯一索引的布尔列(请参阅 this post and this documentation 了解更多详细信息),您将能够通过查询获得每个 product_id
的单个 id
喜欢:
SELECT
id
, product_id
, url
, is_primary
FROM table
WHERE is_primary
我之所以提到这一点,是因为如果您的数据库是以这种方式设置的,那么它是过滤到单个唯一值的非常好的方法。根据您的 table 大小,它也可能更高效,因为 Postgres 将在磁盘上有一个索引并且不需要对所有可能的记录进行排序。
如果您的目标是实际删除 table 中的重复记录,一种方法是使用有效记录形成查询(例如上述之一),然后使用它作为带有 WHERE NOT EXISTS 子句的 DELETE 语句的 USING 子句。
您可以使用 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
。