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?