我本意是将表中的一个字段拆分成多行,例如'aaa,bbb'拆分为
'aaa'
'bbb'
现在测试如下:
with t1 as 
(
     select 3 c1,'eee,fff,ggg' c2 from dual UNION ALL 
     select 2 c1,'ccc,ddd' c2 from dual UNION ALL 
     SELECT 1 c1,'aaa,bbb' c2 FROM dual
)
 
select c1,LEVEL,replace(regexp_substr(c2,'[^,]+',1,level),',',' ') c2
from t1 
connect BY level<=length(c2)-length(replace(c2,',',''))+1
order by c1,level返回结果如下:
C1 LEVEL C2
1 1 aaa
1 2 bbb
1 2 bbb
1 2 bbb
2 1 ccc
2 2 ddd
2 2 ddd
2 2 ddd
3 1 eee
3 2 fff
3 2 fff
3 2 fff
3 3 ggg
3 3 ggg
3 3 ggg
3 3 ggg
3 3 ggg
3 3 ggg
3 3 ggg
3 3 ggg
3 3 ggg--======================================================
看起来connect by之后产生了大量重复数据,于是加入distinct后取得正确数据。
反思:
我构造的测试数据仅仅只有三行,最长的拆分资料仅3段'eee,fff,ggg',却产生了21笔资料。如果测试数据增多,或者需拆分的段
数量增多,那么connect by产生的数据将是海量的。
用此种方法实际处理生产库数据时,问题马上显现出来,仅17笔资料,最长拆分字段为8段,竟然产生了738万笔资料,尽管我使用
了distinct,依然慢的很。我的想法是如何只取每个level的第一个数值,避免重复数据,请教下各位大侠有没有合适的方法,请指教!

解决方案 »

  1.   

    最好的办法个人认为是写一个自定义函数SPLIT,这个应该是效率最高也最可靠的一种方式。这个函数你上网搜索一下应该很多例子的。另外下面提供了一种思路,但是这个方法的问题在于LEVEL的定义,要根据实际情况,看看你的待分隔字段最多能分出多少个记录select t.*,regexp_substr(c2,
                         '[^,]+',
                         1,
                         l_count) from t1 t,(select level l_count from dual connect by level <= 3)
     where regexp_substr(c2,
                         '[^,]+',
                         1,
                         l_count) is not null
      

  2.   


    select regexp_substr('a,b', '[^,]+',1,rownum) from dual connect by 
    rownum<=length('a,b')-length(replace('a,b', ',', ''))+1;
      

  3.   

    select regexp_substr('a,b', '[^,]+',1,rownum) from dual connect by 
        rownum<=length('a,b')-length(replace('a,b', ',', ''))+1;
      

  4.   

    oracle对字符串的操作本来就不甚强大,至于出现了这样的需求,没有办法,只能变通.但是能不能从根本上解决这个问题还是要考虑一下.