首页 > 其他 > 详细

Oralce 按分隔符把一列转成多行

时间:2014-01-17 09:07:29      阅读:374      评论:0      收藏:0      [点我收藏+]

1.前言

  最近因项目需求,需要把员工的工作组返回给前台,但是数据库是把员工的工作组Id,都存在一个字段内了(以“逗号”分隔),而这样不符合前台的需要,他们需要一行,一行的数据。如:

  数据库:

userId, workgroup
1001   10,12,15
1002    2,4,5

  前台需要:

bubuko.com,布布扣
userId, workgroup
1001   10
1001   12
1001   15
1002   2
1002   4
1002   5
bubuko.com,布布扣

 

2. 分析思路:

  大体的思路是这样的:

  首先:要知道,每一员工最多有多少个组。

  其次:建一个有关“数”的临时表,与上面的组数进行关联,这样就出现了“多”行

  最后:多“行”有了,剩下的就是对每一行的组进行刷选。如第一行取第一个逗号左边的,第二行取第二个逗号左边的, 依此类推。

 

3. 实现:

  根据上次的思路,来实现:

  第一步: 

bubuko.com,布布扣
with v_usergroups as (select 1001 as userId,10,12,15 as workgroups from dual
                      union
                      select 1002 as userId,2,4,5 as workgroups from dual
                      )      
select userid,, || workgroups ||, AS tempgroups,length(workgroups || ,) - nvl(length(REPLACE(workgroups, ,)), 0) AS groupcount FROM v_usergroups
bubuko.com,布布扣

  PS: 这里在"workgroup" 的前后也加了逗号,是为了后面使用方面。

  第二步:

select LEVEL lv from dual CONNECT BY LEVEL <= 5

  PS:这里的5,我们是根据业务需要,每一员工最多分为5个组,当然也可以写其他的值,但一定要大于第一步求得的"groupcount".

 

  到这里后,我们对这两个表进行关联,看看值怎么样:

bubuko.com,布布扣
with v_usergroups as (select 1001 as userId,10,12,15 as workgroups from dual
                      union
                      select 1002 as userId,2,4,5 as workgroups from dual
                      )      
select * from 
(select userid,, || workgroups ||, AS tempgroups,length(workgroups || ,) - nvl(length(REPLACE(workgroups, ,)), 0) AS groupcount FROM v_usergroups ) a,
(select LEVEL lv from dual CONNECT BY LEVEL <= 5) b where b.lv<=a.groupcount 
order by userid,lv
bubuko.com,布布扣

 

bubuko.com,布布扣
       USERID    TEMPGROUPS    GROUPCOUNT    LV
1    1001    ,10,12,15,    3    1
2    1001    ,10,12,15,    3    2
3    1001    ,10,12,15,    3    3
4    1002    ,2,4,5,    3    1
5    1002    ,2,4,5,    3    2
6    1002    ,2,4,5,    3    3
bubuko.com,布布扣

  到这里,就离我们最终的结果很近了。 只需要在外层对"tempgroups"做一下简单的处理就可以了:

  第三步:

    这一步的主要思路就是:截串。第一个组应该是第一逗号和第二个逗号之间的值,第二个组应该是第二个逗号与第三个逗号之间的值,那第一个,和第二个如何表示呢,其实就是利用字段lv。也就是:

    substr(tempgroups,instr(tempgroups, ‘,‘, 1, lv) + 1,instr(tempgroups, ‘,‘, 1, lv + 1) - (instr(tempgroups, ‘,‘, 1, lv) + 1))

     最后的SQL 如下:

bubuko.com,布布扣
with v_usergroups as (select 1001 as userId,10,12,15 as workgroups from dual
                      union
                      select 1002 as userId,2,4,5 as workgroups from dual
                      )      
select userid,substr(tempgroups,instr(tempgroups, ,, 1, lv) + 1,instr(tempgroups, ,, 1, lv + 1) - (instr(tempgroups, ,, 1, lv) + 1)) from 
(select userid,, || workgroups ||, AS tempgroups,length(workgroups || ,) - nvl(length(REPLACE(workgroups, ,)), 0) AS groupcount FROM v_usergroups ) a,
(select LEVEL lv from dual CONNECT BY LEVEL <= 5) b where b.lv<=a.groupcount 
order by userid,lv
bubuko.com,布布扣

Oralce 按分隔符把一列转成多行

原文:http://www.cnblogs.com/hankuikui/p/3523013.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!