【问题标题】:Remove duplicate SQL rows by looking at all columns通过查看所有列删除重复的 SQL 行
【发布时间】:2016-09-28 20:30:53
【问题描述】:

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

field001 field002 field003 field004 field005 .... field500

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

(是的,这应该在 TheDailyWTF 中。不,这不是我的错。请耐心等待)。

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

这个表有 1200 万行,所以我不想重新创建它。

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

所以我想我会创建另一个表并用它们加载它。然后我会做某种连接,比较两个表上的所有列,然后从第一个表中删除相等的行。我尝试了 NATURAL JOIN,因为它看起来很有希望,但没有返回任何内容。

我有什么选择?

我使用的是 Amazon Redshift(我记得是 PostgreSQL 8.4),但我认为这是一个一般性的 SQL 问题。

【问题讨论】:

  • 您要删除所有个重复的行还是保留其中的一个?
  • 正如我在帖子前面所说的,我有数据,所以如果我运行的任何查询都删除了所有重复的行,那就没问题了。我可以再次加载集合,一次。

标签: sql postgresql amazon-redshift


【解决方案1】:

您可以在 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);

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • CREATEXID 似乎是某种 Netezza (?) SQL 扩展。 Redshift 几乎是普通的 Postgres。请重新阅读我的帖子,然后再试一次。谢谢!
    【解决方案3】:

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

    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;
    

    【讨论】:

    • 我有 1200 万行。我宁愿不要。
    【解决方案4】:

    这是一个技巧,但可能会有所帮助。

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

    delete from my_table where xmin = <the_wrong_transaction_id>;
    

    PS:小心点,先在某个测试台上试一下。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-11-25
      • 1970-01-01
      • 1970-01-01
      • 2020-02-17
      • 2022-01-14
      • 2011-04-16
      • 1970-01-01
      相关资源
      最近更新 更多