зацикливание в sql с разделителем - PullRequest
0 голосов
/ 24 мая 2019

У меня только что была идея, как я могу выполнить цикл в sql?

Например, у меня есть этот столбец

PARAMETER_VALUE E,C;S,C;I,X;G,T;S,J;S,F;C,S;

Я хочу сохранить все значения до (,) во временном столбце, а также сохранить все значения после (;) в другом столбце, затем он не остановится, пока не останется больше значения после (;)

Ожидаемый выводдля примера

COL1 E S I G S S C

COL2 C C X T J F S

и т. д.,.

Ответы [ 2 ]

2 голосов
/ 24 мая 2019

Вы можете получить, используя regexp_substr() оконную аналитическую функцию с connect by level <= предложением

with t1(PARAMETER_VALUE) as
(
 select 'E,C;S,C;I,X;G,T;S,J;S,F;C,S;' from dual
), t2 as
( 
select level as rn,
       regexp_substr(PARAMETER_VALUE,'([^,]+)',1,level) as str1,
       regexp_substr(PARAMETER_VALUE,'([^;]+)',1,level) as str2
  from t1
connect by level <= regexp_count(PARAMETER_VALUE,';') 
)
select listagg( regexp_substr(str1,'([^;]+$)') ,' ') within group (order by rn) as col1,
       listagg( regexp_substr(str2,'([^,]+$)') ,' ') within group (order by rn) as col2 
  from t2;

COL1            COL2
-------------   -------------
E S I G S S C   C C X T J F S

Демо

1 голос
/ 24 мая 2019

Предполагая, что вам нужно разделить входные данные на строки с разделителями ;, а затем на столбцы с разделителями ,, вы можете сделать что-то вроде этого:

-- WITH clause included to simulate input data. Not part of the solution;
-- use actual table and column names in the SELECT statement below.
with 
  t1(id, parameter_value) as (
    select 1, 'E,C;S,C;I,X;G,T;S,J;S,F;C,S;' from dual union all
    select 2, ',U;,;V,V;'                    from dual union all
    select 3, null                           from dual
  )
-- End of simulated input data
select  id,
        level as ord,
        regexp_substr(parameter_value, '(;|^)([^,]*),', 1, level, null, 2) as col1,
        regexp_substr(parameter_value, ',([^;]*);'    , 1, level, null, 1) as col2
from    t1
connect by  level <= regexp_count(parameter_value, ';') 
        and id = prior id 
        and prior sys_guid() is not null
order   by id, ord
;

 ID ORD COL1 COL2
--- --- ---- ----
  1   1 E    C   
  1   2 S    C   
  1   3 I    X   
  1   4 G    T   
  1   5 S    J   
  1   6 S    F   
  1   7 C    S   
  2   1      U   
  2   2          
  2   3 V    V   
  3   1         

Примечание -это не самый эффективный способ разделения входных данных (ничто не будет очень эффективным - причина - модель данных, которая нарушает первую нормальную форму).Это можно улучшить, используя стандартные instr и substr, но запрос будет более сложным, и по этой причине его будет сложнее обслуживать.

Я сгенерировал больше входных данных, чтобы проиллюстрировать несколько вещей.У вас может быть несколько входов, которые должны быть разбиты одновременно;это должно быть сделано с осторожностью.(Обратите внимание на дополнительные условия в CONNECT BY).Я также иллюстрирую обработку NULL - если запятая идет сразу после точки с запятой, это означает, что часть столбца этой пары должна быть NULL.Это показано в выводе.

...