使用版本爲11g及以上
對於aaa,bbb,ddd,ggg
這樣的字符串,可以使用connect語句將其拆分
with tab1 as (
select 'aaa,bbb,ddd,ggg' str from dual
)
select t1.str,
regexp_substr(t1.str, '[^,]+', 1, level) res,
level
from tab1 t1
connect by level <= regexp_count(t1.str, ',') + 1
;
STR | RES | LEVEL |
---|---|---|
aaa,bbb,ddd,ggg | aaa | 1 |
aaa,bbb,ddd,ggg | bbb | 2 |
aaa,bbb,ddd,ggg | ddd | 3 |
aaa,bbb,ddd,ggg | ggg | 4 |
網上經常可以找到這樣的例子,這寫的也沒有什麼問題。但是當所分隔的值中存在null時,就有問題了。
with tab1 as (
select 'aaa,bbb,,ddd,,,ggg' str from dual
)
select t1.str,
regexp_substr(t1.str, '[^,]+', 1, level) res,
level
from tab1 t1
connect by level <= regexp_count(t1.str, ',') + 1
;
STR | RES | LEVEL |
---|---|---|
aaa,bbb,ddd,ggg | aaa | 1 |
aaa,bbb,ddd,ggg | bbb | 2 |
aaa,bbb,ddd,ggg | ddd | 3 |
aaa,bbb,ddd,ggg | ggg | 4 |
aaa,bbb,ddd,ggg | 5 | |
aaa,bbb,ddd,ggg | 6 | |
aaa,bbb,ddd,ggg | 7 |
而我們真正想要的結果應該是這樣的
STR | RES | LV |
---|---|---|
aaa,bbb,ddd,ggg | aaa | 1 |
aaa,bbb,ddd,ggg | bbb | 2 |
aaa,bbb,ddd,ggg | 3 | |
aaa,bbb,ddd,ggg | ddd | 4 |
aaa,bbb,ddd,ggg | 5 | |
aaa,bbb,ddd,ggg | 6 | |
aaa,bbb,ddd,ggg | ggg | 7 |
這裏本應該使用更加巧妙的正則表達式來解決的,但是我一時沒想到,就先用下面的方法來湊合了
with tab1 as (
select 'aaa,bbb,,ddd,,,ggg' str from dual
)
, tab2 as (
select t1.str,
regexp_substr(t1.str, '[^,]*', 1, level) res,
lag(regexp_substr(t1.str, '[^,]*', 1, level)) over(order by level) lg,
max(regexp_substr(t1.str, '[^,]*', 1, level))
over(order by level rows between current row and unbounded following) mx,
level lv
from tab1 t1
connect by level <= regexp_count(t1.str, ',') * 2 + 1
)
select t1.str,
t1.res,
row_number() over(order by t1.lv) lv
from tab2 t1
where t1.mx is not null
and (t1.res is not null
or (t1.res is null and t1.lg is null)
)
;