如何在没有主键的情况下删除PostgreSQL表中100%重复的行?

时间:2019-10-28 15:03:21

标签: postgresql duplicates sql-delete

我有一个带有大量列的PostgreSQL表。该表没有主键,现在包含几行,它们是另一行的100%复制。

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

我在related question上找到了这个答案,但是我必须拼写出每个列的名称,这很容易出错。 如何避免不必了解表结构?

示例:

给予

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!')

1 个答案:

答案 0 :(得分:0)

根据this answer中的建议,使用system column ctid来区分原本相同的行的物理副本。

为避免为行拼出不存在的“键”,只需使用row constructor 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中进行尝试。