SQL:如何在单独的表中更新重复项?

时间:2015-09-16 10:37:32

标签: sql postgresql duplicates

我有两张桌子:

Table1:    
id1 | id2
1   | a
2   | a
3   | a
4   | b
5   | b

Table2:    
data | id1
...  | 1
...  | 2
...  | 2
...  | 3
...  | 4
...  | 5

Table1我应该有id1-> id2的唯一关联,由于某些未知原因,它不是。我需要修复它并添加唯一约束。 我需要在Table1处仅保留一对一的关系,并仅使用Table2处剩下的ID更新Table1处的重复ID。结果我应该:

Table1:    
id1 | id2
1   | a
4   | b

Table2:    
data | id1
...  | 1
...  | 1
...  | 1
...  | 1
...  | 4
...  | 4

我知道如何找到重复的ID:

SELECT id1 FROM Table1 GROUP BY id2 HAVING COUNT(id2) > 1;

但是我对如何进行下一次更新和移除感到有点迷失。

id1和id2的数据类型是 UUID

2 个答案:

答案 0 :(得分:1)

将问题视为保持第一个关系。然后,删除不是那么难:

delete from table1
     where table1.id1 > (select min(tt1.id1) from table1 tt1 where tt1.id2 = table1.id2);

现在,为了修复table2,我们需要一个更复杂的查询来保存结果。幸运的是,Postgres允许CTE包含数据修改步骤:

with todelete as (
      select t1.*, min(t1.id1) over (partition by id2) as keepid
      from table1
     ),
     d as (
      delete from table1   
      where table1.id > (select min(tt1.id) from table1 tt1 where tt1.id2 = table1.id2)
    )
update table2
    set id1 = (select keepid from todelete where todelete.id1 = table2.id2);

答案 1 :(得分:0)

最简单的方法是编写一个proc,这将是以下内容。

1)从table1中找到不同的id2。

2)对于每个不同的id2,你应该开始一个循环,它应该遵循

  • 对于id2(让我们说'a')找到Table1中的所有id1并存储在一个变量中(如1,2,3)。保持最低的id1(在这种情况下为1)在另一个变量中。 现在为table2生成一个更新语句,设置id2 = lowestid,其中id2 in(id 1,2,3列表)

    生成更新语句后,执行并提交。

完成更新后,您可以使用Gordon的查询进行删除。

如果有许多行需要更新,那么你可以在循环上设置计数器并创建更新语句,后跟';'并附加在变量/游标中,并根据您的数据在每100到200行之后执行。

我不是postgresql的家伙,所以请注意有关proc的任何明显错误。但逻辑应该有效。