我在PostgreSQL 12数据库中有表text_table
,表只有两列:text1
和text2
。
idx_text1
列上有一个text1
索引。
例如:
text1 text2
----------------------
1 str1 one
2 str2 two
3 str3 three
4 str2 two
5 str1 seven
6 str4 seven
7 str3 three
如何删除所有重复的行(两列中的值完全匹配)?
在上面的示例中,需要删除 4 和 7 行(或 2 和 3 )在桌子上。
我想找到一种使用SQL查询的最快方法。
答案 0 :(得分:1)
没有主键,这样的任务很繁琐。我认为最简单的方法可能是备份/还原,如下所示:
create table tmptable as select distinct text1, text2 from mytable;
truncate table mytable; -- back it up first!!
insert into mytable select * from tmptable;
drop table tmptable;
答案 1 :(得分:1)
最佳性能取决于表的大小,并发活动,数量和平均值。行大小,以及最重要的是要删除的行数。
对于只有很少的重复项,没有NULL值(或者您不考虑这些重复项),也没有PRIMARY KEY
,这样做就可以了:
DELETE FROM text_table t
WHERE EXISTS (
SELECT FROM text_table
WHERE (text1, text2) = (t.text1, t.text2)
AND ctid < t.ctid -- exclude self
-- AND pk < t.pk -- alternative with PK
);
在重复项中,这使行的ctid
最小(实际上是第一个)。 (或者使用alt。语法的PK值最小的一个。)
关于ctid
:
您在(text1)
上的索引会有所帮助。除非字符串很长,否则(text1, text2)
上的索引通常会提供更多帮助。 (OTOH,在删除所有行的很大一部分时,索引所产生的成本可能大于收益。)
并考虑在删除重复项之后添加UNIQUE
索引或约束,以防止重新引入更多这些索引或约束。
相关: