将分隔的表拆分成行

时间:2017-08-14 07:49:49

标签: sql oracle plsql delimiter

我有一些非常类似的数据:

ID  STATUS                  EMPL
1   Created;Solved;Closed   John;Terry;Martin

当然,每行中的值的数量可以从1到n。我在1列上找到了一些建议(使用Connect by with regexp_substr)

有没有办法(SQL或PL / SQL明智)获得所需的输出:

ID  STATUS   EMPL
1   Created  John
1   Solved   Terry
1   Closed   Martin

由于

2 个答案:

答案 0 :(得分:2)

with d (id, status, empl) as 
(
  select 1   ,'Created;Solved;Closed',                 'John;Terry;Martin'          from dual union all
  select 2   ,'Created2;Reviewed2;Solved2;Closed2',    'John2;Bell2;Terry2;Martin2' from dual
) 
,cte(id, status, s, e, empl, s1, e1, rn) as 
(
  select 
    id, status, 1, case when instr(status, ';') > 0 then instr(status, ';') else length(status)+1 end, 
          empl, 1, case when instr(empl, ';')   > 0 then instr(empl, ';')   else length(empl)+1 end, 0  
  from d
  union all 
  select 
    id, status,  e+1, case when instr(status, ';' , e+1) > 0 then instr(status, ';', e+1) else length(status)+1 end,  
          empl, e1+1, case when instr(empl, ';'  , e1+1) > 0 then instr(empl, ';',  e1+1) else length(empl)+1 end, rn+1 
  from cte where e <= length(status)
  -- assumption: equal number of delimiters (;) in status and empl column values
)
select id, substr(status, s, e - s) status, substr(empl, s1, e1 - s1) empl  from cte
order by id,rn
;

        ID STATUS                             EMPL                     
---------- ---------------------------------- --------------------------
         1 Created                            John                       
         1 Solved                             Terry                      
         1 Closed                             Martin                     
         2 Created2                           John2                      
         2 Reviewed2                          Bell2                      
         2 Solved2                            Terry2                     
         2 Closed2                            Martin2                    

答案 1 :(得分:0)

不确定大表的性能,但这个选择应该有效

select st.id, st.status, em.empl from (
    select distinct id, level as lvl, regexp_substr(status,'[^;]+',1,level) as status 
    from to_split connect by regexp_substr(status,'[^;]+',1,level) is not null
) st
join (
    select distinct id, level as lvl, regexp_substr(empl,'[^;]+',1,level) as empl 
    from to_split connect by regexp_substr(empl,'[^;]+',1,level) is not null
) em
on st.id = em.id and st.lvl = em.lvl
order by id;