在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提供:
我必须创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数据。
第五个查询,删除/删除不必要的临时表。
所以最终结果是,原始表只有唯一的入口,没有重复。