[英]Recursive CTE (T-SQL) Returns Un-expected Result
我一直在盯着這段代碼WAY,試圖弄清楚為什么我的最終查詢返回意外結果。
任何幫助將非常感激。 提前致謝。
給定以下代碼(在SQL Server 2008 R2上運行):
USE tempdb; DECLARE @emp--loyee TABLE ( EmployeeID int NOT NULL ,EmployeeName nvarchar(50) NOT NULL PRIMARY KEY(EmployeeID) ) INSERT INTO @emp SELECT 1,'Fred' UNION SELECT 2,'Mary' UNION SELECT 3,'Joe' UNION SELECT 4,'Bill' DECLARE @grp TABLE ( GroupID int NOT NULL ,GroupName nvarchar(50) PRIMARY KEY(GroupID) ) INSERT INTO @grp SELECT 1,'Group 1' UNION SELECT 2,'Group 2' UNION SELECT 3,'Group 3' DECLARE @empgrp TABLE ( EmployeeID int NOT NULL ,GroupID int NOT NULL PRIMARY KEY (EmployeeID,GroupID) ) INSERT INTO @empgrp SELECT 1,1 UNION SELECT 2,1 UNION SELECT 3,1 UNION SELECT 4,2 DECLARE @grpgrp TABLE ( GroupID int NOT NULL ,ParentGroupID int ,UNIQUE CLUSTERED(GroupID,ParentGroupID) ) INSERT INTO @grpgrp SELECT 1,2 UNION SELECT 2,3; WITH AllEmpGroups (EmployeeID,GroupID,RootGroupID) AS ( SELECT CAST(NULL as int) as EmployeeID,pgrp.GroupID,pgrp.ParentGroupID FROM @grpgrp pgrp LEFT JOIN @grpgrp ggrp ON pgrp.ParentGroupID = ggrp.GroupID UNION ALL SELECT e.EmployeeID,eg.GroupID,aeg.RootGroupID FROM @emp e JOIN @empgrp eg ON e.EmployeeID = eg.EmployeeID JOIN @grpgrp ggrp ON eg.GroupID = ggrp.GroupID JOIN AllEmpGroups aeg ON aeg.GroupID = ggrp.ParentGroupID ) SELECT EmployeeID,GroupID,RootGroupID FROM AllEmpGroups
我得到的是:
+------------+---------+-------------+ | EmployeeID | GroupID | RootGroupID | +------------+---------+-------------+ | NULL | 1 | 2 | | NULL | 2 | 3 | | 1 | 1 | 3 | | 2 | 1 | 3 | | 3 | 1 | 3 | +------------+---------+-------------+
我期望/想要得到的是:
+------------+---------+-------------+ | EmployeeID | GroupID | RootGroupID | +------------+---------+-------------+ | NULL | 1 | 2 | | NULL | 2 | 3 | | 4 | 2 | 3 | | 1 | 1 | 3 | | 2 | 1 | 3 | | 3 | 1 | 3 | +------------+---------+-------------+
最重要的是,我想要給定根組下所有雇員的完整遞歸堆棧,每行上都有根組ID。
我想念什么?
第一:
@grpgrp
的根節點需要一行,其值為3, null
union all
之前的部分)必須是祖先第一次遞歸的根節點( 3, null
)。 ...
INSERT INTO @grpgrp
SELECT 1,2
UNION all
SELECT 2,3
UNION all
select 3, null;
WITH AllEmpGroups (EmployeeID,GroupID,RootGroupID)
AS
(
SELECT CAST(NULL as int) as EmployeeID,pgrp.GroupID, ParentGroupID = pgrp.GroupID
FROM @grpgrp pgrp LEFT JOIN @grpgrp ggrp
ON pgrp.ParentGroupID = ggrp.GroupID
where pgrp.ParentGroupId is null
UNION ALL
SELECT e.EmployeeID,eg.GroupID,aeg.RootGroupID
FROM @emp e JOIN @empgrp eg
ON e.EmployeeID = eg.EmployeeID
JOIN @grpgrp ggrp
ON eg.GroupID = ggrp.GroupID
JOIN AllEmpGroups aeg
ON aeg.GroupID = ggrp.ParentGroupID
)
SELECT EmployeeID,GroupID,RootGroupID
FROM AllEmpGroups
extrester演示: http ://rextester.com/CBWY80387
收益:
+------------+---------+-------------+
| EmployeeID | GroupID | RootGroupID |
+------------+---------+-------------+
| NULL | 3 | 3 |
| 4 | 2 | 3 |
| 1 | 1 | 3 |
| 2 | 1 | 3 |
| 3 | 1 | 3 |
+------------+---------+-------------+
除此之外,我將首先構建組層次結構, 然后像這樣加入員工:
WITH AllEmpGroups (GroupID,ParentGroupID,RootGroupID)
AS
(
SELECT pgrp.GroupID, pgrp.ParentGroupID, RootGroupId = GroupID
FROM @grpgrp pgrp
where pgrp.ParentGroupId is null
UNION ALL
SELECT ggrp.GroupID,ggrp.ParentGroupID,aeg.RootGroupID
FROM @grpgrp ggrp
inner JOIN AllEmpGroups aeg
ON aeg.GroupID = ggrp.ParentGroupID
)
SELECT eg.EmployeeID,aeg.*
FROM AllEmpGroups aeg
left JOIN @empgrp eg
ON eg.GroupID = aeg.GroupID
extrester演示: http ://rextester.com/FAK76354
收益:
+------------+---------+---------------+-------------+
| EmployeeID | GroupID | ParentGroupID | RootGroupID |
+------------+---------+---------------+-------------+
| NULL | 3 | NULL | 3 |
| 4 | 2 | 3 | 3 |
| 1 | 1 | 2 | 3 |
| 2 | 1 | 2 | 3 |
| 3 | 1 | 2 | 3 |
+------------+---------+---------------+-------------+
從...開始
WITH AllGroups (RootGroupID,GroupID,ParentGroupID, level)
AS
(
SELECT GroupID RootGroupID, GroupID, Cast(NULL as int) ParentGroupID, 0 level
FROM @grp g
WHERE NOT EXISTS (SELECT 1 FROM @grpgrp gg WHERE gg.GroupID = g.GroupID)
UNION ALL
SELECT ag.RootGroupID, gg.GroupID, gg.ParentGroupID, level+1
FROM @grpgrp gg
JOIN AllGroups ag
ON ag.GroupID = gg.ParentGroupID
)
SELECT EmployeeID, ag.GroupID, ParentGroupID, RootGroupID
FROM AllGroups ag
LEFT JOIN @empgrp eg ON eg.GroupID = ag.GroupID
ORDER BY RootGroupID, level, ParentGroupID, GroupID;
不確定為什么需要該行:
| NULL | 2 | 3 |
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.