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

问题描述 投票:0回答:5

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

empID 员工姓名 经理ID
100 莎拉 110
101 111
102 亚历克斯 110
110 罗斯 111
111 周一

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

员工 员工姓名 副老板 副老板姓名 老板 老板姓名
100 莎拉 110 罗斯 111 周一
101 111 周一
102 亚历克斯 110 罗斯 111 周一
110 罗斯 111 周一
111 周一
sql oracle connect-by
5个回答
1
投票

您还可以使用 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
;

在这里测试


1
投票

Ankit Bajpai 的答案由于使用 root 连接而在 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;

小提琴


0
投票

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

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;

或者,您可以使用分层查询和数据透视:

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;

两个输出:

EMPID EMP 名称 小BOSS 小老板姓名 老大 老板姓名
100 莎拉 110 罗斯 111 周一
102 亚历克斯 110 罗斯 111 周一
101 111 周一
110 罗斯 111 周一
111 周一

db<>小提琴这里


0
投票

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;

演示。


0
投票

请找到这个

带有 as ( 选择 empID emp,empName empName,之前的 empID subBoss,之前的 empName subBossName,之前的经理 ID Boss 来自雇员 以 managerID 为空开始 通过先前的 empID = managerID 连接 排序依据 1) 选择a.*,b.empName BossName 从一个 左连接 emp b 在 a.boss = b.empID
按 1 排序;

© www.soinside.com 2019 - 2024. All rights reserved.