zoukankan      html  css  js  c++  java
  • Oralce 按分隔符把一列转成多行

    1.前言

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

      数据库:

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

      前台需要:

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

    2. 分析思路:

      大体的思路是这样的:

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

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

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

    3. 实现:

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

      第一步: 

    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

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

      第二步:

    select LEVEL lv from dual CONNECT BY LEVEL <= 5

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

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

    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
           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

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

      第三步:

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

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

         最后的SQL 如下:

    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
  • 相关阅读:
    chown
    [NOI2010]航空管制
    批量kill 某个用户session
    【BZOJ2395】【Balkan 2011】Timeismoney 最小乘积生成树
    找出 alter system kill session ‘sid,serial#’ kill 掉的数据库会话对应进程
    [NOI2016]优秀的拆分
    Oracle12C查询自建用户(非系统自带)
    查询包含某个字段的表
    [WC2011]最大XOR和路径
    监控慢SQL
  • 原文地址:https://www.cnblogs.com/hankuikui/p/3523013.html
Copyright © 2011-2022 走看看