【问题标题】:delete duplicates in a table and update references删除表中的重复项并更新引用
【发布时间】:2020-09-14 03:03:57
【问题描述】:

我有一个带有 id 的表,我们现在添加了一个新字段,我们从外部来源计算唯一性,这让我们意识到我们实际上在数据库中有重复:

主表

id | unique_id | ...
---|------------
4  | A         |
5  | A
6  | B

我们可以看到:5 实际上是 4 的副本,因为它们都有相同的 unique_id

现在需要清理一下。

很遗憾,我不能简单地删除那些重复项 (5),因为其他表依赖于它:

其他表 (OtherTable.main_id REFERENCES MainTable.id)

id | main_id | ...
---|------------
1  | 4       | Blah
2  | 5
3  | 6

现在我要清理重复的,在这里

UPDATE OtherTable SET main_id = 5 WHERE main_id=4

如何在有效的更新中做到这一点? 我尝试使用相同的unique_id 简单地更新对第一个引用的每个引用,但这并没有在一天内完成。

UPDATE "OtherTable" SET "main_id" = (SELECT "id" FROM "MainTable" WHERE "unique_id" = (SELECT "unique_id" FROM "MainTable" WHERE "id" == "OtherTable"."main_id") LIMIT 1)

如果有帮助,MainTable 包含大约 750,000 个条目,OtherTable 包含 12,000,000 行。

可能那是因为那些三重选择一的效率很低。

对于删除重复项的简单部分(在我完成将引用更改为第一个类似的引用之后)我发现这个查询工作得足够快:

DELETE FROM MainTable
    WHERE id IN
        (SELECT id
        FROM
            (SELECT id,
             ROW_NUMBER() OVER( PARTITION BY unique_id
            ORDER BY  id ) AS row_num
            FROM MainTable ) t
            WHERE t.row_num > 1 );

但是我需要一种方法来更新对未删除重复项的引用。

【问题讨论】:

  • 请不要混淆更新和删除。你想要什么?
  • @wildplasser 更新所有引用重复项的表,然后删除重复项。

标签: postgresql


【解决方案1】:

我建议不要使用UPDATE 进行嵌套查询,而是使用UPDATE FROM 进行连接,并使用与DELETE 语句中相同的窗口函数:

UPDATE "OtherTable" AS other
SET main_id = main.min_id
FROM (SELECT
    id,
    first_value(id) OVER (PARTITION BY unique_id ORDER BY id) AS min_id
  FROM "MainTable"
) AS main
WHERE main.id = other.main_id
  AND main.id <> main.min_id

【讨论】:

    猜你喜欢
    • 2017-06-12
    • 1970-01-01
    • 2019-04-21
    • 2013-10-13
    • 2010-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多