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 |
+-----------+---------+------------+----------+
这是我的 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 |
+-----------+---------+------------+----------+