2013-07-02 40 views
1

我們可以使用「Connect By」從oracle中的分隔字符串生成行。像:「Connect By」根據多個分隔字符串生成行

SELECT Rn ,Regexp_Substr(data, '[^,]+', 1, LEVEL) Data 
FROM (SELECT 1 Rn ,'id:a,val:b,desc:c' data FROM Dual) Idata 
CONNECT BY Regexp_Substr(data, '[^,]+', 1, LEVEL) IS NOT NULL 

我想使用內部查詢作爲一個聯合所有幾個記錄。喜歡的東西:

SELECT Rn ,Regexp_Substr(data, '[^,]+', 1, LEVEL) Data 
    FROM (SELECT 1 Rn ,'id:a,val:b,desc:c' data FROM Dual 
     UNION ALL 
     SELECT 2 Rn ,'id:a2,val:b2,desc:c2' data FROM Dual 
     UNION ALL 
     SELECT 3 Rn ,'id:a3,val:b3,desc:c3' data FROM Dual) Idata 
    CONNECT BY Regexp_Substr(data, '[^,]+', 1, LEVEL) IS NOT NULL; 

,這樣我可以得到一個結果集,

RN DATA 
1 desc:c 
1 id:a 
1 val:b 
2 desc:c2 
2 id:a2 
2 val:b2 
3 desc:c3 
3 id:a3 
3 val:b3 

但它不能正常工作,它是如來:

RN DATA 
1 desc:c 
1 desc:c 
1 desc:c 
1 desc:c 
1 desc:c 
1 desc:c 
1 desc:c 
1 desc:c 
1 desc:c 
1 id:a 
1 val:b 
1 val:b 
1 val:b 
2 desc:c2 
2 desc:c2 
2 desc:c2 
2 desc:c2 
2 desc:c2 
2 desc:c2 
2 desc:c2 
2 desc:c2 
: 
: 
: 

應用DISTINCT不目標。因爲這些字符串可能會有所不同,並且在這裏需要花費很多時間來分割更大的字符串。我想,在這個查詢中,LEVEL代不適合。可能是,可能需要使用Rn上的設施。任何人都可以幫我寫這個查詢嗎?謝謝你前進。 :)

回答

1

如果您使用11gR2中您可以使用RCTE:

with Idata as 
(SELECT 1 Rn ,'id:a,val:b,desc:c' data FROM Dual 
     UNION ALL 
     SELECT 2 Rn ,'id:a2,val:b2,desc:c2' data FROM Dual 
     UNION ALL 
     SELECT 3 Rn ,'id:a3,val:b3,desc:c3' data FROM Dual), 
rcte(rn, txt, token, i) as 
(
    select rn, data, Regexp_Substr(data, '[^,]+', 1, 1), 2 
    from Idata 
    union all 
    select rn, txt, Regexp_Substr(txt, '[^,]+', 1, i), i+1 
    from rcte 
    where Regexp_Substr(txt, '[^,]+', 1, i) IS NOT null 
) 
select rn, token 
from rcte 
order by rn; 

如果沒有,添加DISTINCT是沉重的,那麼你可以嘗試不同的方法,如使用流水線功能 -

create or replace type t is object(token varchar2(100)); 
/
create or replace type t_tab as table of t; 
/
create or replace function split_string(str varchar2, del in varchar2) return t_tab 
    pipelined is 

    token varchar2(4000); 
    str_t varchar2(4000) ; 
    v_del_i number; 


begin 

    str_t := str; 

    while str_t is not null loop 

     v_del_i := instr(str_t, del, 1, 1); 

     if v_del_i = 0 then 
     token := str_t; 
     str_t := ''; 
     else 
     token := substr(str_t, 1, v_del_i - 1); 
     str_t := substr(str_t, v_del_i + 1); 
     end if; 

     pipe row(t(token)); 

    end loop; 

return; 
end split_string; 
/

現在查詢看起來是這樣的:

select t.token, Idata.rn 
from (SELECT 1 Rn ,'id:a,val:b,desc:c' data FROM Dual 
     UNION ALL 
     SELECT 2 Rn ,'id:a2,val:b2,desc:c2' data FROM Dual 
     UNION ALL 
     SELECT 3 Rn ,'id:a3,val:b3,desc:c3' data FROM Dual) Idata , 
     table(split_string(Idata.data, ',')) t 

Here is a sqlfiddle demo

相關問題