使用定界符循环 sql
looping in sql with delimiter
我刚想到如何循环 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
等。 . .
你可以通过使用 regexp_substr()
window 带有 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
假设您需要在 ;
分隔符处将输入分隔成行,然后在 ,
分隔符处分隔成列,您可以这样做:
-- 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 的处理——如果逗号紧跟在分号之后,这意味着该对的 "column 1" 部分必须为 NULL。这显示在输出中。
我刚想到如何循环 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
等。 . .
你可以通过使用 regexp_substr()
window 带有 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
假设您需要在 ;
分隔符处将输入分隔成行,然后在 ,
分隔符处分隔成列,您可以这样做:
-- 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 的处理——如果逗号紧跟在分号之后,这意味着该对的 "column 1" 部分必须为 NULL。这显示在输出中。