【问题标题】:"Connect By" to generate rows from multiple delimited string“连接方式”从多个分隔字符串生成行
【发布时间】:2013-07-02 06:49:23
【问题描述】:

我们可以使用“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 上的按设施分组。任何人都可以帮我写这个查询吗?提前谢谢。 :)

【问题讨论】:

    标签: sql oracle recursive-query delimited connect-by


    【解决方案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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-04
      • 1970-01-01
      • 2021-11-28
      • 2012-02-02
      • 2010-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多