I have two tables UPD_REF and UPD_TO
CREATE TABLE UPD_REF
( ref number(10)
);
CREATE TABLE UPD_TO
( ref number(10),
name varchar2(50)
);
INSERT INTO UPD_REF (ref) VALUES (2);
INSERT INTO UPD_REF (ref) VALUES (3);
INSERT INTO UPD_TO (ref, name) VALUES (1, 'ORG');
INSERT INTO UPD_TO (ref, name) VALUES (2, 'ORG');
INSERT INTO UPD_TO (ref, name) VALUES (2, 'ORG');
INSERT INTO UPD_TO (ref, name) VALUES (2, 'ORG');
INSERT INTO UPD_TO (ref, name) VALUES (3, 'ORG');
There is no key and we can have duplicates in both tables UPD_TO or UPD_REF.
I need to update the same count of rows on UPD_TO corresponding to UPD_REF.
If I do a simple update or merge like this:
merge into UPD_TO USING UPD_REF
on (UPD_TO.ref = UPD_REF.ref)
when matched then
update set UPD_TO.name = 'SET';
I have all the matching values updated:
REF NAME
---- ----
1 ORG
2 SET
2 SET
2 SET
3 SET
But I need to get that:
REF NAME
---- ----
1 ORG
2 SET
2 ORG
2 ORG
3 SET
Any clues ?
Advertisement
Answer
You can update your rows by rowid, but first you need to identify that single row in each group by some ordering criteria in ROW_NUMBER()
. The code is:
merge into upd_to
using (
select t.rowid,
row_number() over(
partition by t.ref
order by 1 /*Put your ordering to raise that single row to top of order by*/ asc
) as rn
from UPD_TO t
where ref in (
select f.ref
from upd_ref f
)
) u
on (upd_to.rowid = u.rowid and u.rn = 1)
when matched then update
set name = 'SET'
| REF | NAME |
+-----+------+
|1 | ORG |
|2 | ORG |
|2 | ORG |
|2 | SET |
|3 | SET |
If your table has more columns, then it may be good solution. If this is the exact table you have and you need to have a count of rows with the same ID
and NAME
, then it is better not to insert new rows, but update and count rows (of course, altering table before with new column for counter):
merge into UPD_TO
using (select <new data> ) new_data
on (UPD_TO.ref = new_data.ref)
when matched then update
set item_count = item_count + new_data.item_count
when not matched then insert
values(new_data.id, new_data.name, new_data.item_count)
I cannot imagine another useful reason to have such two-column table with duplicates, that’s why I’ve asked for clarification of the purpose.
UPD: New version, that updates the same row count per REF
, that UPD_REF
has, with fiddle containing duplicates in UPD_REF
.
merge into upd_to
using (
with base as (
select t.rowid,
t.ref,
row_number() over(partition by t.ref order by 1) as rn
from UPD_TO t
)
select rowid
from base
where (ref, rn) in (
select
f.ref,
row_number() over(partition by f.ref order by 1) as rn2
from upd_ref f
)
) u
on (upd_to.rowid = u.rowid)
when matched then update
set name = 'SET'