【发布时间】:2015-10-23 14:19:21
【问题描述】:
我有一个像follow这样的表
+-----------+------------+
| ManagerID | EmployeeID |
+-----------+------------+
| MAN001 | BOY001 |
| MAN001 | BOY002 |
| MAN001 | BOY003 |
| MAN001 | BOY004 |
| MAN001 | BOY005 |
| BOY005 | KID001 |
| BOY005 | KID002 |
| BOY005 | KID003 |
| BOY005 | KID004 |
| MAN002 | BOY005 |
| MAN002 | BOY004 |
| BOY004 | KID001 |
| BOY004 | KID002 |
| BOY004 | KID003 |
| BOY004 | KID004 |
| KID002 | SOM001 |
| KID002 | SOM002 |
| KID002 | SOM003 |
+-----------+------------+
主要的一点是 EmployeeID 中不存在 MAN001,这意味着 MAN001 是顶级的。 但是 BOY005 可以用于 MAN001 或 MAN002 等等... 与 KID00X 相同,可以与任何经理 MAN00X 或 BOY00X 一起使用。
也有可能 KID001 KID002 KID003 KID004 可能有一个员工,例如 KID002 有三个员工 SOM001 SOM002 和 SOM003 但是 BOY005 永远不会是 KID 的员工,因为我们知道 BOY005 是 KID 的经理。
我想得到的输出如下,其中列 E 可以增长与数据一样多。
+--------+--------+--------+--------+-------+
| M1 | E1 | E2 | E3 | ... |
+--------+--------+--------+--------+-------+
| MAN001 | BOY001 | | | |
| MAN001 | BOY002 | | | |
| MAN001 | BOY003 | | | |
| MAN001 | BOY004 | | | |
| MAN001 | BOY005 | KID001 | | |
| MAN001 | BOY005 | KID002 | | |
| MAN001 | BOY005 | KID003 | | |
| MAN001 | BOY005 | KID004 | | |
| MAN001 | BOY005 | KID002 | SOM001 | |
| MAN001 | BOY005 | KID002 | SOM002 | |
| MAN001 | BOY005 | KID002 | SOM003 | |
+--------+--------+--------+--------+-------+
我尝试遵循这个基本的简单递归 cte。但是该示例没有考虑员工是否存在于多个经理中。 http://blog.sqlauthority.com/2008/07/28/sql-server-simple-example-of-recursive-cte/
上述博客文章的另一个不同情况是,在我的情况下,顶级 ManagerID 根本不存在于 EmployeeID 中
WITH Emp_CTE AS (
SELECT EmployeeID, ManagerID
FROM Employee
WHERE ManagerID IS NULL
UNION ALL
SELECT e.EmployeeID, , e.ManagerID
FROM HumanResources.Employee e
INNER JOIN Emp_CTE ecte ON ecte.EmployeeID = e.ManagerID
)
SELECT *
FROM Emp_CTE
谢谢
编辑1:
这与我正在寻找的非常接近。 我也认为KID00X不能直接在MAN001下。 有没有更高效的自动化方式?
select PC.ManagerID,PC.EmployeeID,PC2.EmployeeID,PC3.EmployeeID
, PC4.EmployeeID, PC5.EmployeeID
from Employee PC
LEFT JOIN (select ManagerID,EmployeeID from Employee
where ManagerID in (select EmployeeID from Employee))PC2 ON PC2.ManagerID=PC.EmployeeID
LEFT JOIN (select ManagerID,EmployeeID from Employee
where ManagerID in (select EmployeeID from Employee
where ManagerID in (select EmployeeID from Employee)))PC3 ON PC3.ManagerID=PC2.EmployeeID
LEFT JOIN (select ManagerID,EmployeeID from Employee
where ManagerID in (select EmployeeID from Employee
where ManagerID in (select EmployeeID from Employee
where ManagerID in (select EmployeeID from Employee))))PC4 ON PC4.ManagerID = PC3.EmployeeID
LEFT JOIN (select ManagerID,EmployeeID from Employee
where ManagerID in (select EmployeeID from Employee
where ManagerID in (select EmployeeID from Employee
where ManagerID in (select EmployeeID from Employee
where ManagerID in (select EmployeeID from Employee)))))PC5 ON PC5.ManagerID = PC4.EmployeeID
Order by PC.ManagerID,PC.EmployeeID,PC2.EmployeeID,PC3.EmployeeID
, PC4.EmployeeID, PC5.EmployeeID
【问题讨论】:
-
您将面临的最大挑战是动态列数。递归 cte 并不是什么大问题,但需要遍历树将非常具有挑战性,也很可能是一个巨大的性能问题。您可以查看这篇文章,以了解解决问题的稍微不同的方法。 sqlservercentral.com/articles/Hierarchy/94040
-
谢谢。我在原始帖子中以手动方式编写递归查询。是否可以对其进行优化,甚至可以优化递归的自动化程度?再次感谢,我会查看您的链接
-
您的编辑可能有效,也可能无效。使用这种格式,它只是一堵难以辨认的文字墙。从外观来看,它的问题在于仅限于 5 个级别。当你再上一层时会发生什么?这就是你必须使用动态 sql 的原因。
标签: sql sql-server tsql common-table-expression