2017-04-05 97 views
2

我一直在盯着这段代码太长,试图找出为什么我的最终查询返回意外的结果。递归CTE(T-SQL)返回非预期结果

任何帮助将不胜感激。提前致谢。

 
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 

我得到的是::

考虑下面的代码(SQL Server 2008 R2上运行)

 
+------------+---------+-------------+ 
| 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在每一行上。

我错过了什么?

+0

如何使用'hierarchyid'数据类型。 – Hackerman

+0

从“SQL Server 2008”开始https://docs.microsoft.com/en-us/sql/t-sql/data-types/hierarchyid-data-type-method-reference – Hackerman

回答

2

第一:

  1. 您需要为根节点行@grpgrp与递归CTE值3, null
  2. 锚(在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 

rextester演示: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 

rextester演示: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 | 
+------------+---------+---------------+-------------+ 
+0

非常感谢。感谢额外的建议,首先完成层次结构,然后加入员工! – klzbrt

+0

@klzbrt乐意帮忙! – SqlZim

2

开始

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 | 
+0

简单而直接。谢谢。 – klzbrt