使用connect by分隔列

时间:2016-09-24 20:58:03

标签: oracle oracle11g connect-by

我有一个父子关系中有行的表。最大父子关系深度为3.

一位家长只有一个孩子。

表格定义 -

CREATE TABLE USERS {
    empid NUMBER,
    name VARCHAR2,
    department VARCHAR2(20),
    oldempid NUMBER,
}

数据 -

EMPID NAME DEPARTMENT OLDEMPID
    1  FOO         IT        2
    2 null         HR        4
    3  BAR      ADMIN     null
    4 null     DESIGN     null

期望的输出 -

EMPID NAME DEPARTMENT_1 DEPARTMENT_2 DEPARTMENT_3
    1  FOO           IT           HR       DESIGN
    3  BAR        ADMIN         null         null

完全所需的输出 -

EMPID NAME DEPARTMENT_1 DEPARTMENT_2 DEPARTMENT_3 OLDEMPID_1 OLDEMPID_2
    1  FOO           IT           HR       DESIGN          2          4
    3  BAR        ADMIN         null         null       null       null

我尝试过使用CONNECT BY PRIOR

SELECT CONNECT_BY_ROOT EMPID,
       NAME,
         RTRIM(LTRIM(SYS_CONNECT_BY_PATH(DEPARTMENT, '-'), '-'), '-') AS DEPARTMENT,
         RTRIM(LTRIM(SYS_CONNECT_BY_PATH(OLDEMPID, '-'), '-'), '-') AS OLDEMPID
   FROM USERS
   WHERE CONNECT_BY_ISLEAF = 1
   CONNECT BY PRIOR OLDEMPID = EMPID;

我得到的输出是 -

EMPID   NAME    DEPARTMENT     OLDEMPID
    1    null   IT-HR-DESIGN   1-2-4   
    3    BAR    ADMIN              null

1 个答案:

答案 0 :(得分:2)

您还需要透视结果。您可以手动执行此操作,也可以使用PIVOT操作(因为您使用oracle11g标记了这个 - 这是PIVOT可用的第一个版本)。子查询(在FROM子句中朝向结尾)是层次结构查询,使用" connect by。"

with
     users ( EMPID, NAME, DEPARTMENT, OLDEMPID ) as (
       select 1, 'FOO', 'IT'    ,    2 from dual union all
       select 2, null , 'HR'    ,    4 from dual union all
       select 3, 'BAR', 'ADMIN' , null from dual union all
       select 4, null,  'DESIGN', null from dual
     ),
     tops ( empid ) as ( 
       select empid    from users minus 
       select oldempid from users
     )
select cbr_empid as empid, cbr_name as name,
       "1_DEPARTMENT" as department_1, "2_DEPARTMENT" as department_2, 
       "3_DEPARTMENT" as department_3, "2_EMPID" as oldempid_2, "3_EMPID" as oldempid_3
from (
       select empid, department, level as lvl, 
              connect_by_root(empid) as cbr_empid, connect_by_root(name) as cbr_name
       from   users
       connect by prior oldempid = empid
       start with empid in (select empid from tops)
     )
pivot ( max(department) as department, max(empid) as empid for lvl in (1, 2, 3))
;

输出:

     EMPID NAME DEPARTMENT_1 DEPARTMENT_2 DEPARTMENT_3 OLDEMPID_2 OLDEMPID_3
---------- ---- ------------ ------------ ------------ ---------- ----------
         1 FOO  IT           HR           DESIGN                2          4
         3 BAR  ADMIN