我们可以使用“Connect By”从oracle中的分隔字符串生成行。像:
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上的设施。任何人都可以帮我写这个查询吗?谢谢你提前。 :)
答案 0 :(得分: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 强>