Я немного изменил вашу таблицу и добавил столбец ID, который однозначно идентифицирует строку, поэтому он выглядит следующим образом:
SQL> select * from test;
ID COL1 COL2
---------- ------------------------------ ------------------------------
1 1234, 5623, 1236,1567 5623, 9089,1567,2890,1234
2 145,126,1236,1478 1748,8956,1234,1478
Этот подход
- разбивает все столбцыв строки (
t_one
для col1
, t_two
для col2
) inter
CTE использует оператор набора INTERSECT
для поиска общих значений, которые должны быть удалены изрезультат t1_new
и t2_new
агрегировать новые значения столбца (используя функцию LISTAGG
) - окончательный
SELECT
возвращает окончательный результат
Вот оно:
SQL> with
2 t_one as
3 (select id,
4 trim(regexp_substr(col1, '[^,]+', 1, column_value)) c1
5 from test,
6 table(cast(multiset(select level from dual
7 connect by level <= regexp_count(col1, ',') + 1
8 ) as sys.odcinumberlist))
9 ),
10 t_two as
11 (select id,
12 trim(regexp_substr(col2, '[^,]+', 1, column_value)) c2
13 from test,
14 table(cast(multiset(select level from dual
15 connect by level <= regexp_count(col2, ',') + 1
16 ) as sys.odcinumberlist))
17 ),
18 inter as
19 (select t1.id, t1.c1 cx from t_one t1
20 intersect
21 select t2.id, t2.c2 cx from t_two t2
22 ),
23 t1_new as
24 (select a.id, listagg(a.c1, ',') within group (order by a.c1) c1_new
25 from (select t1.id, t1.c1 from t_one t1
26 minus
27 select i.id, i.cx from inter i
28 ) a
29 group by a.id
30 ),
31 t2_new as
32 (select b.id, listagg(b.c2, ',') within group (order by b.c2) c2_new
33 from (select t2.id, t2.c2 from t_two t2
34 minus
35 select i.id, i.cx from inter i
36 ) b
37 group by b.id
38 )
39 select a.id, a.c1_new, b.c2_new
40 from t1_new a join t2_new b on a.id = b.id;
ID C1_NEW C2_NEW
---------- -------------------- --------------------
1 1236 2890,9089
2 1236,126,145 1234,1748,8956
SQL>