在PostgreSQL中删除完全重复的行(并且只保留1)

我在PostgreSQL 8.3.8数据库中有一个表,它没有任何键/约束,并且有多个具有完全相同值的行。

我想删除所有重复项,并保持每行只有一个副本。

有一列(特别是“钥匙”),可以用来标识重复(即每个不同的“钥匙”应该只有一个条目)。

我怎样才能做到这一点? (最好用一个单一的SQL命令)在这种情况下速度不是问题(只有几行)。

DELETE FROM dupes a WHERE a.ctid <> (SELECT min(b.ctid) FROM dupes b WHERE a.key = b.key); 

更快的解决scheme是

 DELETE FROM dups a USING ( SELECT MIN(ctid) as ctid, key FROM dups GROUP BY key HAVING COUNT(*) > 1 ) b WHERE a.key = b.key AND a.ctid <> b.ctid 

我试过这个:

 DELETE FROM tablename WHERE id IN (SELECT id FROM (SELECT id, ROW_NUMBER() OVER (partition BY column1, column2, column3 ORDER BY id) AS rnum FROM tablename) t WHERE t.rnum > 1); 

由Postgres wiki提供:

https://wiki.postgresql.org/wiki/Deleting_duplicates

我必须创build我自己的版本。 由@a_horse_with_no_name编写的版本在我的表(21M行)上太慢了。 而@rapimo根本不会删除dups。

这是我在PostgreSQL 9.5上使用的

 DELETE FROM your_table WHERE ctid IN ( SELECT unnest(array_remove(all_ctids, actid)) FROM ( SELECT min(b.ctid) AS actid, array_agg(ctid) AS all_ctids FROM your_table b GROUP BY key1, key2, key3, key4 HAVING count(*) > 1) c); 

我会用一个临时表:

 create table tab_temp as select distinct f1, f2, f3, fn from tab; 

然后,删除tab并将tab_temp重命名为tab

这对我很好。 我有一张表,包含重复值的条款。 执行一个查询来填充所有重复行的临时表。 然后我用temp表中的这些id运行了一条delete语句。 值是包含重复项的列。

  CREATE TEMP TABLE dupids AS select id from ( select value, id, row_number() over (partition by value order by value) as rownum from terms ) tmp where rownum >= 2; delete from [table] where id in (select id from dupids) 

这是快速和简洁:

 DELETE FROM dupes T1 USING dupes T2 WHERE T1.ctid < T2.ctid -- delete the older versions AND T1.key = T2.key; -- add more columns if needed 

正常SQL和POSTGRESQL工作(也在AWS REDSHIFT中工作)

 DROP TABLE IF EXISTS backupOfTheTableContainingDuplicates; CREATE TABLE aNewEmptyTemporaryOrBackupTable AS SELECT DISTINCT * FROM originalTableContainingDuplicates; TRUNCATE TABLE originalTableContainingDuplicates; INSERT INTO originalTableContainingDuplicates SELECT * FROM aNewEmptyTemporaryOrBackupTable ; DROP TABLE aNewEmptyTemporaryOrBackupTable ; 

对上述SQL脚本的解释

所以,

第一个查询可以确保,如果您有任何包含重复的原始表的备份/临时表,那么首先删除该表。

第二个查询创build一个新的表(Temporary / Backup)表,其中包含重复的原始表中的唯一条目,所以新的临时表与原始表MINUS重复的条目相同。

第三个查询,截断或清空原始表。

第四个查询,将临时表中的所有唯一条目插入或复制到最近被截断的原始表(因此没有数据)。 执行此查询后,原始表将填充临时表中的UNIQUE数据。

第五个查询,删除/删除不必要的临时表。

所以最终结果是,原始表只有唯一的入口,没有重复。