簡體   English   中英

遞歸CTE(T-SQL)返回意外結果

[英]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。

我想念什么?

第一:

  1. @grpgrp的根節點需要一行,其值為3, null
  2. 遞歸cte的錨(在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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM