繁体   English   中英

Oracle - 在分层查询中使用先连接并将它们放入行中

[英]Oracle - using connect by prior in Hierarchical Queries and put them into rows

我是 Oracle 的新手,我将在实现平面表而不是分层表之前使用 connect by。 但我有点困惑。 我的表是这样的:empTabl:

员工编号 员工姓名 经理ID
100 萨拉 110
101 111
102 亚历克斯 110
110 罗斯 111
111 星期一 NULL

我将像这样更改表格(输出):

雇员 员工姓名 副老板 subBossName 老板 老板姓名
100 萨拉 110 罗斯 111 星期一
101 111 星期一 NULL NULL
102 亚历克斯 110 罗斯 111 星期一
110 罗斯 111 星期一 NULL NULL
111 星期一 NULL NULL NULL NULL

您可以为此使用递归子查询因式分解子句:

WITH hierarchy (empID, empName, subBoss, subBossName, boss, bossName, depth, managerId) AS (
  SELECT empID,
         empName,
         CAST(NULL AS NUMBER),
         CAST(NULL AS VARCHAR2(20)),
         CAST(NULL AS NUMBER),
         CAST(NULL AS VARCHAR2(20)),
         1,
         managerID
  FROM   empTbl
UNION ALL
  SELECT h.empID,
         h.empName,
         CASE h.depth
         WHEN 1 THEN e.empID
         ELSE h.subBoss
         END,
         CASE h.depth
         WHEN 1 THEN e.empName
         ELSE h.subBossName
         END,
         CASE h.depth
         WHEN 2 THEN e.empID
         ELSE h.boss
         END,
         CASE h.depth
         WHEN 2 THEN e.empName
         ELSE h.bossName
         END,
         h.depth + 1,
         e.managerID
  FROM   hierarchy h
         LEFT OUTER JOIN empTbl e
         ON (h.managerID = e.empID)
  WHERE  depth < 3
)
CYCLE empID, depth SET is_cycle TO 1 DEFAULT 0
SELECT empID, empName, subBoss, subBossName, boss, bossName
FROM   hierarchy
WHERE  depth = 3;

或者,您可以使用分层查询和 pivot:

SELECT emp_id AS empID,
       emp_name AS empName,
       subboss_id AS subbossid,
       subboss_name AS subbossname,
       boss_id AS bossid,
       boss_name AS bossname
FROM   (
  SELECT CONNECT_BY_ROOT(empID) AS root_empid,
         empID,
         empName,
         LEVEL AS depth
  FROM   empTbl
  WHERE  LEVEL <= 3
  CONNECT BY PRIOR managerID = empID
)
PIVOT (
  MAX(empID) AS id,
  MAX(empName) AS name
  FOR depth IN (
    1 AS emp,
    2 AS subBoss,
    3 AS boss
  )
)
ORDER BY empid;

其中,对于样本数据:

CREATE TABLE empTbl (empID, empName, managerID) AS
SELECT 100, 'Sara', 110 FROM DUAL UNION ALL
SELECT 101, 'Ben',  111 FROM DUAL UNION ALL
SELECT 102, 'Alex', 110 FROM DUAL UNION ALL
SELECT 110, 'Ross', 111 FROM DUAL UNION ALL
SELECT 111, 'Mon',  NULL FROM DUAL;

output:

EMPID 企业名称 副总裁 副老板名 老板 老板名
100 萨拉 110 罗斯 111 星期一
102 亚历克斯 110 罗斯 111 星期一
101 111 星期一
110 罗斯 111 星期一
111 星期一

db<> 在这里摆弄

您也可以为此目的使用 connect by 子句。

select empID, empName
  , subBoss, subBossName
  , (select boss.empID from YourTable boss where boss.empID = subBossManagerID) Boss
  , (select boss.empName from YourTable boss where boss.empID = subBossManagerID) BossName
from (
  select empID, empName
    , prior empID subBoss, prior empName subBossName
    , prior t.managerID subBossManagerID
  from YourTable t
  start with managerID is null
  connect by prior empID = managerID
)
order by 1
;

在这里测试

MDO 答案的较短版本是 -

WITH DATA AS (SELECT 100 AS empID, 'Sara' AS empName, 110 AS managerID FROM DUAL UNION ALL
              SELECT 101, 'Ben', 111 FROM DUAL UNION ALL
              SELECT 102, 'Alex', 110 FROM DUAL UNION ALL
              SELECT 110, 'Ross', 111 FROM DUAL UNION ALL
              SELECT 111, 'Mon', NULL FROM DUAL)
 SELECT empID emp, empName, prior empID subBoss, prior empName subBossName
    , prior t.managerID Boss
    ,CASE WHEN PRIOR t.managerID IS NOT NULL THEN CONNECT_BY_ROOT(t.empName) END AS BossName
  FROM DATA T
 START WITH managerID IS NULL
CONNECT BY PRIOR empID = managerID
  ORDER BY 1;

演示。

由于使用 root 连接,Ankit Bajpai 的回答在 4 级之后为经理提供了错误的名称。 通过小通知,此查询给出最短答案

WITH DATA AS (SELECT 100 AS empID, 'Sara' AS empName, 110 AS managerID FROM DUAL UNION ALL
              SELECT 101, 'Ben', 111 FROM DUAL UNION ALL
              SELECT 102, 'Alex', 110 FROM DUAL UNION ALL
              SELECT 110, 'Ross', 111 FROM DUAL UNION ALL
              SELECT 111, 'Mon', NULL FROM DUAL)
, b as( SELECT p.empID , p.empName, p.managerID, m.empName as managerName  FROM DATA p left join data m
   on ( p.managerID=m.empID))
 SELECT empID emp, empName, prior empID subBoss, prior empName subBossName
    , prior managerID Boss, prior managerName BossNAme
  FROM b
 START WITH managerID IS NULL
CONNECT BY PRIOR empID = managerID
  ORDER BY 1;

小提琴

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM