我有两张桌子:
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 。
答案 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的任何明显错误。但逻辑应该有效。