将具有逗号分隔值的 Oracle 行扩展为多行
我在 Oracle 中有一个如下所示的表:
KEY,VALS
k1,"a,b"
我需要它看起来像:
KEY,VAL
k1,a
k1,b
我使用 CONNECT BY
和 LEVEL
执行此操作,遵循 示例:
with t as (
select 'k1' as key, 'a,b' as vals
from dual
)
select key, regexp_substr(vals, '[^,]+', 1, level) as val
from t
connect by LEVEL <= length(vals) - length(replace(vals, ',')) + 1
但是当我在桌子,并且 vals
可以是不同长度的逗号分隔值,例如:
KEY,VALS
k1,"a,b"
k2,"c,d,e"
我正在寻找类似的结果:
KEY,VAL
k1,a
k1,b
k2,c
k2,d
k2,e
但是上面的简单方法不起作用,因为 每个级别都与其上面的级别相连,导致:
with t as (
select 'k1' as key, 'a,b' as vals
from dual
union
select 'k2' as key, 'c,d,e' as vals
from dual
)
select key, regexp_substr(vals, '[^,]+', 1, level) as val
from t
connect by LEVEL <= length(vals) - length(replace(vals, ',')) + 1
KEY,VAL
k1,a
k1,b
k2,e
k2,d
k2,e
k2,c
k1,b
k2,e
k2,d
k2,e
我怀疑我需要某种CONNECT BY PRIOR 条件,但我不确定是什么。尝试按键匹配时:
connect by prior key = key
and LEVEL <= length(vals) - length(replace(vals, ',')) + 1
我收到 ORA-01436: CONNECT BY Loop in user data
错误。
这里正确的方法是什么?
I have a table in Oracle like the following:
KEY,VALS
k1,"a,b"
I need it to look like:
KEY,VAL
k1,a
k1,b
I did this with CONNECT BY
and LEVEL
, following an example:
with t as (
select 'k1' as key, 'a,b' as vals
from dual
)
select key, regexp_substr(vals, '[^,]+', 1, level) as val
from t
connect by LEVEL <= length(vals) - length(replace(vals, ',')) + 1
But when I have multiple rows in the table, and the vals
can be comma-delimited values of different lengths, like:
KEY,VALS
k1,"a,b"
k2,"c,d,e"
I'm looking for a result like:
KEY,VAL
k1,a
k1,b
k2,c
k2,d
k2,e
But the naive approach above doesn't work because every level is connected with the one above it, resulting in:
with t as (
select 'k1' as key, 'a,b' as vals
from dual
union
select 'k2' as key, 'c,d,e' as vals
from dual
)
select key, regexp_substr(vals, '[^,]+', 1, level) as val
from t
connect by LEVEL <= length(vals) - length(replace(vals, ',')) + 1
KEY,VAL
k1,a
k1,b
k2,e
k2,d
k2,e
k2,c
k1,b
k2,e
k2,d
k2,e
I suspect I need some kind of CONNECT BY PRIOR condition, but I'm not sure what. When trying to match by keys:
connect by prior key = key
and LEVEL <= length(vals) - length(replace(vals, ',')) + 1
I get an ORA-01436: CONNECT BY loop in user data
error.
What's the right approach here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
选项 1:简单、快速的字符串函数和递归查询:
选项 2:LATERAL 连接的分层查询中较慢的正则表达式
此选项需要 Oracle 12 或更高版本。
选项 3:与父行相关的递归查询。
此选项是最慢的选项,因为它需要在层次结构的各个级别之间进行关联并在每个步骤生成 GUID(这看似无用,但可以防止不必要的递归)。
其中所有输出:
db<>fiddle 此处
Option 1: Simple, fast string functions and a recursive query:
Option 2: Slower regular expressions in a LATERAL joined hierarchical query
This option requires Oracle 12 or later.
Option 3: Recursive query correlating to parent rows.
This option is the slowest of the options as it needs to correlate between levels of the hierarchy and generate a GUID at each step (which is seemingly useless but prevents unnecessary recursion).
Which all output:
db<>fiddle here