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'