Разбиение строки на несколько строк в Oracle, разделенных конвейером - PullRequest
0 голосов
/ 31 января 2020

У меня есть данные в Oracle, которые имеют 3 столбца и выглядят так:

username    user.prof    values
__________________________________________
user_name1       user.prof1       1|2|3
user_name2       user.prof2       NOT_REQUIRED
user_name3       user.prof3       779|678|1|2|3

Как вы можете видеть, значения разделены символом трубы, и их число не является фиксированным. Желаемый результат:

username    user.prof    values
__________________________________________
user_name1    user.prof1    1
user_name1    user.prof1    2
user_name1    user.prof1    3
user_name2    user.prof2    NOT_REQUIRED
user_name3    user.prof3    779
user_name3    user.prof3    678
user_name3    user.prof3    1
user_name3    user.prof3    2
user_name3    user.prof3    3

Может кто-нибудь помочь мне с этим? Спасибо !!

Ответы [ 2 ]

1 голос
/ 31 января 2020

Вот один из вариантов:

SQL> with test (username, user_prof, value) as
  2    (select 'user_name1', 'user.prof1', '1|2|3'         from dual union all
  3     select 'user_name2', 'user.prof2', 'NOT_REQUIRED'  from dual union all
  4     select 'user_name3', 'user.prof3', '779|678|1|2|3' from dual
  5    )
  6  select
  7    username,
  8    user_prof,
  9    regexp_substr(value, '[^\|]+', 1, column_value) value
 10  from test cross join
 11       table(cast(multiset(select level from dual
 12                           connect by level <= regexp_count(value, '\|') + 1
 13                          ) as sys.odcinumberlist));

USERNAME   USER_PROF  VALUE
---------- ---------- ----------------------------------------------------
user_name1 user.prof1 1
user_name1 user.prof1 2
user_name1 user.prof1 3
user_name2 user.prof2 NOT_REQUIRED
user_name3 user.prof3 779
user_name3 user.prof3 678
user_name3 user.prof3 1
user_name3 user.prof3 2
user_name3 user.prof3 3

9 rows selected.

SQL>
0 голосов
/ 31 января 2020

Для этого вам понадобится рекурсивный cte:

WITH split_values ( username, values1, start1, end1 ) AS (
  SELECT username, values1, 1, instr( values1, '|', 1 )
  FROM  table_name
  UNION ALL
  SELECT username, values1, end1 + 1, INSTR( values1, '|', end1 + 1 )
  FROM   split_values
  WHERE  end1 > 0
)
SELECT username, 
      CASE end1
          WHEN 0 THEN SUBSTR( values1, start1 )
       ELSE SUBSTR( values1, start1, end1 - start1 )
       END AS values1
FROM   split_values
...