PostgreSQL消除父子表中的重复条目

vwkv1x7d  于 2022-11-23  发布在  PostgreSQL
关注(0)|答案(1)|浏览(125)

我正在编写一些脚本来清理一些数据。因为我们无法复制生产数据库,所以我们不得不手动将一些测试数据加载到两个表中,这两个表与生产数据库中的表具有相同的结构和数据分布。
我们使用PostgreSQL 12.8
表很大,填充这两个表需要很大的努力。为了加速插入,我们删除了这两个表中的所有索引。在加载结束时,当我们想要重新创建索引时,我们发现意外地将一些数据加载了两次。
假设我们的表如下所示:

table_1:                 table_2:

     id                  id    value 
    ----               --------------
  1 id-1             1   id-1  v-1   
  2 id-1             2   id-1  v-2
  3 id-2             3   id-1  v-3
  4 id-2             4   id-1  v-4
  5 id-3             5   id-2  v-5
                     6   id-2  v-6
                     7   id-2  v-7
                     8   id-2  v-8
                     9   id-3  v-9
                    10   id-3  v-10

正如您在table_1中看到的,行号2)和4)是重复的。我们希望用其他内容替换它们;比如id-4id-5。我们如何计算新ID并不重要,它必须是唯一的。它可以是任何东西,甚至是id-1-dedupid-2-dedup,但对于table_2中一半的重复ID来说,这一点非常重要,以便获得相同的修复。应用修复后,我希望我们的两个表如下所示:

table_1:                 table_2:

     id                  id    value 
    ----               --------------
  1 id-1             1   id-1  v-1   
  2 id-4             2   id-1  v-2
  3 id-2             3   id-4  v-3
  4 id-5             4   id-4  v-4
  5 id-3             5   id-2  v-5
                     6   id-2  v-6
                     7   id-5  v-7
                     8   id-5  v-8
                     9   id-3  v-9
                    10   id-3  v-10

哪一行获得新ID无关紧要,我们只想消除table_1中的重复项并反映table_2中的更改。Pity merge语句在PostgreSQL 12.8中不可用
删除数据并重新插入它实际上不是一个选项,因为填充value列需要大量工作,只有在没有其他聪明方法的情况下,我们才会这样做。
先谢谢你了。

pbossiut

pbossiut1#

我将采取的方法是向这两个表中添加一个串行列。然后,您可以运行以下更新:

WITH cte as 
(SELECT serial_col, row_number() over(partition by id) as rn
FROM table_1)
UPDATE table_1 
SET id = table_1.id || '-dup'
FROM cte
WHERE cte.serial_col = table_1.serial_col AND cte.rn = 2;

WITH cte as 
(SELECT serial_col, row_number() over(partition by id) as rn
FROM table_2)
UPDATE table_2 
SET id = table_2.id || '-dup'
FROM cte
WHERE cte.serial_col = table_2.serial_col AND cte.rn > 2;

请注意,这是假设您只有重复项而没有三重项。
运行更新后,如有必要,可以删除串行列。

相关问题