Вы можете использовать аналитический агрегат, чтобы получить наименьшее значение rid
для каждого rval
:
min(rid) over (partition by rval)
и используйте его в подзапросе, который объединяет две таблицы (которые я с воображением назвал t1
и t2
, поскольку вы не дали их настоящие имена), чтобы вы могли видеть самые подходящие значения rid
для каждой 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
Затем вы можете использовать это в операторе слияния:
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
Как только вы это сделаете, вы можете удалить избыточные значения PK:
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
Id 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
);
Это обновит каждую строку; если у вас много данных и / или небольшая часть должна быть изменена, вы можете добавить фильтр, чтобы обновлять только эти:
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
)
where rid != (
select min_rid
from (
select rid, min(rid) over (partition by rval) as min_rid from t1
) x
where x.rid = t2.rid
);