我要清理我的桌子:
rid(PK) rval
----------- ----------
10 test
11 Rtest
12 dummy
13 test
14 Rtest
要从列rval
中删除重复的值,所以我最终得到:
rid(PK) rval
----------- ----------
10 test
11 Rtest
12 dummy
但是我还有另一个具有外键关系的表,该表使用我要删除的值:
ruid rid(FK)
---------- ----------
1 10
2 10
3 12
4 13
5 13
6 14
7 14
因此,在删除之前,我需要更新该表以使用我保留的匹配rid
,例如更新14至11;这样该表将最终显示为:
ruid rid(FK)
---------- ----------
1 10
2 10
3 12
4 10
5 10
6 11
7 11
我该怎么做?
答案 0 :(得分:1)
您可以使用分析汇总为每个rid
获得最低的rval
:
min(rid) over (partition by rval)
,并在连接两个表的子查询中使用它(我没有想象出它们的真实名称,我曾想象它们称为t1
和t2
),因此您可以看到最合适的{每个rid
的{1}}:
ruid
然后可以在合并语句中使用它:
select t2.ruid, t2.rid, x.min_rid
from (
select rid, min(rid) over (partition by rval) as min_rid from t1
) x
join t2 on t2.rid = x.rid;
RUID RID MIN_RID
---------- ---------- ----------
1 10 10
2 10 10
3 12 12
4 13 10
5 13 10
6 14 11
7 14 11
完成后,您可以删除冗余PK值:
merge into t2
using (
select t2.ruid, t2.rid, x.min_rid
from (
select rid, min(rid) over (partition by rval) as min_rid from t1
) x
join t2 on t2.rid = x.rid
) y
on (t2.ruid = y.ruid)
when matched then update set t2.rid = y.min_rid
where t2.rid != y.min_rid;
4 rows merged.
select * from t2;
RUID RID
---------- ----------
1 10
2 10
3 12
4 10
5 10
6 11
7 11
Id delete from t1
where exists (select * from t1 x where x.rval = t1.rval and x.rid < t1.rid);
2 rows deleted.
select * from t1;
RID RVAL
---------- -----
10 test
11 Rtest
12 dummy
不是唯一的,并且没有其他唯一键可以包含在语句中,因此您不能真正使用合并-您不能在引用中引用ruid
rid
子句,因为这是您要更新的列。
您可以改为进行相关更新:
on
这将更新每一行;如果您有大量数据和/或需要更改的比例很小,则可以添加过滤器以仅更新那些数据:
update t2
set rid = (
select min_rid
from (
select rid, min(rid) over (partition by rval) as min_rid from t1
) x
where x.rid = t2.rid
);