SQL 服务器父子(父查看所有内容)?

SQL Server parent child (parent see all everything)?

这是我的 table:

EmployeeID  Employee    ManagerID
---------------------------------
    1       Anna           5
    2       John           4
    3       Steve          4
    4       Lisa           1
    5       Adam          NULL
    6       Per            1

我通过这样的自连接获得父子关系没有问题:

SELECT 
    E.EmployeeID,
    E.Employee AS Employee,
    E.ManagerID,
    M.Employee AS Manager
FROM 
    Employee AS E
LEFT JOIN 
    Employee AS M ON E.ManagerID = M.EmployeeID

EmployeeID  Employee    ManagerID   Manager
1   Anna    5   Adam
2   John    4   Lisa
3   Steve   4   Lisa
4   Lisa    1   Anna
5   Adam    NULL NULL
6   Per     1    Anna

但是,我将如何确保父级看到整个层次结构级别?

我希望 table 看起来像这样:

EmployeeID  Manager Employee    EmployeeID  
5   Adam    Anna    1
5   Adam    Per     6
5   Adam    Lisa    4
5   Adam    John    2
5   Adam    Steve   3
1   Anna    Per     6
1   Anna    Lisa    4
1   Anna    John    2
1   Anna    Steve   3
4   Lisa    John    2
4   Lisa    Steve   3

注意:在这个例子中,我只有 3 层马槽,但可以有更多

你可以试试这个:

DECLARE @DataSource TABLE
(
    [EmployeeID] TINYINT
   ,[Employee] VARCHAR(12)
   ,[ManagerID] TINYINT 
);

INSERT INTO @DataSource ([EmployeeID], [Employee], [ManagerID])
VALUES (1, 'Anna', 5)
      ,(2, 'John', 4)
      ,(3, 'Steve', 4)
      ,(4, 'Lisa', 1)
      ,(5, 'Adam', NULL)
      ,(6, 'Per',  1);

WITH DataSource AS 
(
    SELECT DISTINCT DS1.*
                   ,0 AS [Level]
                   ,DS1.[EmployeeID] AS Parent
    FROM @DataSource DS1
    INNER JOIN @DataSource DS2
        ON DS1.[EmployeeID] = DS2.[ManagerID]
    UNION ALL
    SELECT DS2.*
          ,DS1.[Level] + 1
          ,DS1.Parent
    FROM DataSource DS1
    INNER JOIN @DataSource DS2
        ON DS1.[EmployeeID] = DS2.[ManagerID]
)
SELECT DS1.[EmployeeID] 
      ,DS1.[Employee] AS [Manager]
      ,DS.[EmployeeID]
      ,DS.[Employee]
FROM DataSource DS
INNER JOIN @DataSource DS1
    ON DS.[Parent] = DS1.[EmployeeID]
WHERE DS.[Level] <> 0
ORDER BY DS.[Parent] DESC;

我们正在使用递归 CTE,如果您是第一次看到这种语法,它可能看起来有点混乱和复杂,但这没什么特别的。

何时使用递归 CTE 运行 进行一些性能测试以确保它是解决问题的正确技术。

您应该使用递归 CTE 语法。在第一次迭代中(在 UNION ALL 之前),您将获得所有父子对。在递归部分(在 UNION ALL 之后),您将获得每对的下一级子级,并将其替换为父子对,而不是让父级保持不变的子级。

WITH CTE AS 
(
   SELECT TP.EmployeeID as ManagerId, 
          TP.Employee as Manager,
          TC.EmployeeID as EmployeeID, 
          TC.Employee as Employee

          FROM TEmployee as TP
          JOIN TEmployee as TC on (TP.EmployeeID = TC.ManagerID)

          UNION ALL

   SELECT TP.ManagerId as ManagerId, 
          TP.Manager as Manager,
          TC.EmployeeID as EmployeeID, 
          TC.Employee as Employee

          FROM CTE as TP
          JOIN TEmployee as TC on (TP.EmployeeID = TC.ManagerID)
)
SELECT * FROM CTE Order By ManagerID

结果:

+-----------+---------+------------+----------+
| ManagerId | Manager | EmployeeID | Employee |
+-----------+---------+------------+----------+
|         1 | Anna    |          4 | Lisa     |
|         1 | Anna    |          6 | Per      |
|         1 | Anna    |          2 | John     |
|         1 | Anna    |          3 | Steve    |
|         4 | Lisa    |          2 | John     |
|         4 | Lisa    |          3 | Steve    |
|         5 | Adam    |          1 | Anna     |
|         5 | Adam    |          4 | Lisa     |
|         5 | Adam    |          6 | Per      |
|         5 | Adam    |          2 | John     |
|         5 | Adam    |          3 | Steve    |
+-----------+---------+------------+----------+