In the solution below, I use a standard technique to split each comma-separated string into components (tokens) in factored subquery prep. Then I join back to the original table to replace each token (which is an i_id) with the corresponding b_id, and then put the tokens back together into pipe-separated strings with listagg().
Note: This solution assumes that each r_id has fewer than 100 tokens (see the "magic number" 100 in the definition of idx). If it is known that each r_id will have no more than 9 tokens, then 100 can be changed to 10 (resulting in faster processing). If NO upper bound is known beforehand, you can change 100 to some ridiculously large number; 4000 will do if r_id is anything but a CLOB, as VARCHAR2 and such have a limit of 4000 characters.
Thanks to MT0 for reminding me to add this note.
with test_data ( b_id, i_id, r_id ) as (
select 'W00001', 1234, '1235,1237' from dual union all
select 'B00001', 1235, '1236,1235' from dual union all
select 'T00001', 1236, '1235,1235,1235' from dual union all
select 'X00001', 1237, '1234,1236,1238' from dual union all
select 'M00001', 1238, '1238' from dual
),
idx ( n ) as (
select level from dual connect by level < 100
),
prep ( b_id, i_id, n, token ) as (
select t.b_id, t.i_id, i.n,
regexp_substr(t.r_id, '([^,]+)', 1, i.n, null, 1)
from test_data t join idx i
on i.n <= regexp_count(t.r_id, ',') + 1
)
select p.b_id, p.i_id,
listagg(t.b_id, '|') within group (order by p.n) as r_id
from prep p join test_data t
on p.token = t.i_id
group by p.b_id, p.i_id
order by p.i_id;
B_ID I_ID R_ID
------ ---------- ------------------------------
W00001 1234 B00001|X00001
B00001 1235 T00001|B00001
T00001 1236 B00001|B00001|B00001
X00001 1237 W00001|T00001|M00001
M00001 1238 M00001
Added information based on further conversation with MT0.
I edited this "Added information" again based on even more conversation with MT0. Thank you MT0 for keeping me on my toes!
In the solution below I do away with the magic number 100 and instead I use a common technique to deal with multiple input rows and connect by level from dual. I also show a common technique for dealing with duplicates (in the tokens obtained from the comma-separated input strings).
Query:
with
test_data ( b_id, i_id, r_id ) as (
select 'W00001', 1234, '1235,1237' from dual union all
select 'B00001', 1235, '1236,1235' from dual union all
select 'T00001', 1236, '1235,1235,1235' from dual union all
select 'X00001', 1237, '1234,1236,1238' from dual union all
select 'M00001', 1238, '1238' from dual
),
prep ( b_id, i_id, n, token ) as (
select b_id, i_id, level,
regexp_substr(r_id, '([^,]+)', 1, level, null, 1)
from test_data t
connect by level <= regexp_count(r_id, ',') + 1
and prior r_id = r_id -- to only generate the rows needed
and prior sys_guid() is not null -- this is unique, to avoid cycles
),
z ( b_id, i_id, n, token, rn ) as (
select b_id, i_id, n, token,
row_number() over (partition by i_id, token order by n)
from prep
)
select z.b_id, z.i_id,
listagg(t.b_id, '|') within group (order by z.n) as r_id
from z join test_data t
on z.token = t.i_id
where z.rn = 1
group by z.b_id, z.i_id
order by i_id;
Result:
B_ID I_ID R_ID
------ ---------- ------------------------------
W00001 1234 B00001|X00001
B00001 1235 T00001|B00001
T00001 1236 B00001
X00001 1237 W00001|T00001|M00001
M00001 1238 M00001
5 rows selected.