通过查看所有列来删除重复的SQL行

时间:2016-09-28 20:30:54

标签: sql postgresql amazon-redshift

我有这个表,其中每列都是VARCHAR(或等效的):

field001 field002 field003 field004 field005 .... field500

500 VARCHAR列。没有主键。并且不保证任何列都是唯一的。因此,确定两行是否相同的唯一方法是比较所有列的值。

(是的,这应该是在TheDailyWTF。不,这不是我的错。请在这里跟我说。)

我错误地插入了一组重复的行,我需要找到它们并删除它们。

这张桌子上有1200万行,所以我宁愿不重新创建它。

但是,我确实知道错误地插入了哪些行(我有.sql文件)。

所以我想我会创建另一个表并加载它们。然后我会进行某种连接,比较两个表上的所有列,然后删除与第一个表相同的行。我尝试了一个NATURAL JOIN,因为看起来很有希望,但没有回复。

我有什么选择?

我使用的是Amazon Redshift(如果我记得的话,请使用PostgreSQL 8.4),但我认为这是一个普遍的SQL问题。

4 个答案:

答案 0 :(得分:2)

您可以将整行视为Postgres中的单个记录(因此我认为在Redshift中)。

以下在Postgres中有效,并将保留其中一个副本

delete from the_table
where ctid not in (select min(ctid)
                   from the_table
                   group by the_table); --<< Yes, the group by is correct!

这会很慢!

对如此多的列进行分组然后使用NOT IN进行删除将需要相当长的时间。特别是如果要删除很多行。

如果您要删除所有重复行(不保留其中任何一行),您可以使用以下内容:

delete from the_table
where the_table in (select the_table
                    from the_table
                    group by the_table
                    having count(*) > 1);

答案 1 :(得分:0)

您应该能够使用CREATEXID识别所有错误插入的行。如果您按照下面的表格将CREATEXID分组并获得计数,您应该能够了解在事务中插入了多少行并使用DELETE删除它们命令。

SELECT CREATEXID,COUNT(1)
  FROM yourtable
GROUP BY 1;

答案 2 :(得分:0)

一个简单的解决方案是重新创建表格,例如

CREATE TABLE my_temp_table (
    -- add column definitions here, just like the original table
);
INSERT INTO my_temp_table SELECT DISTINCT * FROM original_table;
DROP TABLE original_table;
ALTER TABLE my_temp_table RENAME TO original_table;

甚至

CREATE TABLE my_temp_table AS SELECT DISTINCT * FROM original_table;
DROP TABLE original_table;
ALTER TABLE my_temp_table RENAME TO original_table;

答案 3 :(得分:0)

这是一招,但可能会有所帮助。

表中包含插入/更新行的事务ID的每一行:System Columns。它是xmin列。因此,使用它可以找到插入错误数据的事务ID。然后使用

删除行
delete from my_table where xmin = <the_wrong_transaction_id>;

PS:小心并先在某些测试台上试一试。