Хитрость заключается в том, чтобы выяснить, какой столбец в текущей строке имеет наибольшее количество разделителей и добавить к нему один, и именно столько раз вам нужно будет «зацикливаться» через соединение с помощью.Переменная «level», которая поставляется вместе с connect by, содержит счетчик.Таким образом, объединение подсчитывает разделители в текущей строке, MAX () получает наибольшее число, а затем соединяется по «циклам» столько раз.Обратите внимание, что эта форма регулярного выражения обрабатывает элементы списка NULL, а более распространенная форма '[^,]*'
, используемая для анализа строк, - нет.Смотрите здесь для получения дополнительной информации об этом: https://stackoverflow.com/a/31464699/2543416.
-- This CTE sets up the data with variable list elements
with tbl (id, c1, c2) as (
select 100, 'A,B', '1,2' from dual union all
select 101, 'C,D', '3' from dual union all
select 102, 'E', '4,5' from dual union all
select 103, NULL, '7,8,9' from dual union all
select 104, 'F,G,,I,J', '10,11,12,13,14' from dual -- NULL list element
)
select id,
-- Don't use '[^,]*' it doesn't handle NULL list elements
regexp_substr(c1, '(.*?)(,|$)', 1, level, NULL, 1) part1,
regexp_substr(c2, '(.*?)(,|$)', 1, level, NULL, 1) part2
from tbl a
connect by level <= (select max(count)+1
from (select regexp_count(c1, ',') as count from tbl b where a.id = b.id union
select regexp_count(c2, ',') as count from tbl b where a.id = b.id )
)
and prior id = id
and prior sys_guid() is not null;
ID PART1 PART2
------ -------- --------------
100 A 1
100 B 2
101 C 3
101 D
102 E 4
102 5
103 7
103 8
103 9
104 F 10
104 G 11
104 12
104 I 13
104 J 14
14 rows selected.