首页 > 解决方案 > 如何在没有主键的 PostgreSQL 表中删除 100% 重复的行?

问题描述

我有一个包含大量列的 PostgreSQL 表。该表没有主键,现在包含几行,这些行与另一行 100% 重复。

如何删除这些重复项而不删除原始项?

我在一个相关问题上找到了这个答案,但我必须拼出每个列名,这很容易出错。我怎样才能避免对表结构有所了解?

例子:

给定

create table duplicated (
 id int,
 name text,
 description text
);

insert into duplicated
values (1, 'A', null), 
       (2, 'B', null),
       (2, 'B', null),
       (3, 'C', null), 
       (3, 'C', null), 
       (3, 'C', 'not a DUPE!');

删除后,应保留以下行:

(1, 'A', null) 
(2, 'B', null)
(3, 'C', null) 
(3, 'C', 'not a DUPE!')

标签: postgresqlduplicatessql-delete

解决方案


如this answer中所建议的,使用系统列ctid来区分其他相同行的物理副本。

为了避免为行拼写一个不存在的“键”,只需使用行构造函数 row(table),它返回一个包含整个行的行值,如下所示select * from table

DELETE FROM duplicated
USING (
      SELECT MIN(ctid) as ctid, row(duplicated) as row
        FROM duplicated 
        GROUP BY row(duplicated) HAVING COUNT(*) > 1
      ) uniqued
      WHERE row(duplicated) = uniqued.row
      AND duplicated.ctid <> uniqued.ctid;

您可以在此DbFiddle中尝试。


推荐阅读