我有这个表,其中每列都是VARCHAR(或等效的):
field001 field002 field003 field004 field005 .... field500
500 VARCHAR列。没有主键。并且不保证任何列都是唯一的。因此,确定两行是否相同的唯一方法是比较所有列的值。
(是的,这应该是在TheDailyWTF。不,这不是我的错。请在这里跟我说。)
我错误地插入了一组重复的行,我需要找到它们并删除它们。
这张桌子上有1200万行,所以我宁愿不重新创建它。
但是,我确实知道错误地插入了哪些行(我有.sql文件)。
所以我想我会创建另一个表并加载它们。然后我会进行某种连接,比较两个表上的所有列,然后删除与第一个表相同的行。我尝试了一个NATURAL JOIN,因为看起来很有希望,但没有回复。
我有什么选择?
我使用的是Amazon Redshift(如果我记得的话,请使用PostgreSQL 8.4),但我认为这是一个普遍的SQL问题。
答案 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:小心并先在某些测试台上试一试。