工作和学习中常常会遇到一行要分割成多行数据的情况
,在此整理一下做下对比。
如果表数据只有一行,则
可以直接在原表上
直接使用
connect by
+
正则的方法
,
比如:
select
regexp_substr
(
'444.555.666'
,
'[^.]+'
,
level
)
col
from
dual
connect
level
<=
regexp_count
(
'444.555.666'
,
'\.'
)
输出结果:
如果数据表存在多行数据需要拆分,也可以在原表上使用connect+正则的方法:
with
t
as
(
select
'111.222.333'
col
from
dual
union
select
'444.555.666'
col
from
dual
)
select
regexp_substr
(
col
,
'[^.]+'
,
level
)
from
t
connect
level
<=
regexp_count
(
col
,
'\.\'
)
and
col
=
prior
col
prior
dbms_random.value
>
---------
使用构造的最大行数值关联原表:
with
t
as
(
select
'111.222.333'
col
from
dual
union
select
'444.555.666'
col
from
dual
)
select
regexp_substr
(
col
,
'[^.]+'
,
1
,
lv
)
from
t
,
(
select
level
lv
from
dual
connect
level
10
)
b
where
b.lv
<=
regexp_count
(
t.col
,
'\.\'
)
这种方法设置第二个数据集的时候要小于可能的最大值,然后两数据集做关联,在做大数据量拆分的时候,这个数值设置得当,拆分行数相对一致的情况下,效率比方法一直接connect by要高。
使用table函数:
with
t
as
(
select
'111.222.333'
col
from
dual
union
select
'444.555.666'
col
from
dual
)
select
column_value
from
t
,
table
(
cast
(
multiset
(
select
regexp_substr
(
col
,
'[^.]+'
,
level
)
dd
from
dual
connect
level
<=
regexp_count
(
t.col
,
'\.\'
)
sys.odcivarchar2list
))
a
COLUMN_VALUE
-------------
这个方法输出的列名是固定的,column_value依赖于
sys.odcivarchar2list
这个类型的输出,该方法对于大数据量的拆分效率比第二个方法好。
with
t
as
(
select
'111.222.333'
col
from
dual
union
select
'444.555.666'
col
from
dual
)
select
regexp_substr
(
col
,
'[^.]+'
,
trim
(
column_value
))
from
t
,
xmltable
(
concat
(
'1 to '
,
regexp_count
(
t.col
,
'\.\'
)
1
))
a
;
注意:大数据量的拆分时,谨慎使用正则的方法去做,可以使用substr+instr的方式替换正则。
如果以上方法的效率仍然不理想,可考虑使用plsql块。