[英]Using CONNECT BY PRIOR for a hierarchical query - Oracle SQL
[英]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.