我需要创建一个查询,在查询管理器的层次结构下显示Employee,Manager,Active和活动后代。有人可以帮我吗?
结果:
/* EmployeeId ManagerId IsActive NoofDescendantsActive
1 -1 0 4
2 1 1 3
3 1 0 2
4 2 1 2
6 2 0 0
7 3 1 0
8 3 1 0
9 4 1 1
10 9 1 0
11 9 0 0
* /
create table Person
(
EmployeeId int,
ManagerId int,
IsActive bit
);
insert into Person(EmployeeId,ManagerId,IsActive) values
(1, -1, 0),
(2, 1, 1),
(3, 1, 0),
(4, 2, 1),
(6, 2, 0),
(7, 3, 1),
(8, 3, 1),
(9, 4, 1),
(10, 9, 1),
(11, 9, 0);
答案 0 :(得分:2)
我认为您可以使用以下递归CTE 获得所需的结果:
;WITH Descendants_CTE AS (
-- Anchor member: Get leaf nodes first
SELECT p1.EmployeeId, p1.ManagerId, p1.IsActive, 0 AS level
FROM Person AS p1
WHERE NOT EXISTS (SELECT 1
FROM Person AS p2
WHERE p2.ManagerId = p1.EmployeeId)
UNION ALL
-- Recursive member: Get nodes of next level, keep track of
-- the number of active nodes so far
SELECT p.EmployeeId, p.ManagerId, p.IsActive, level = level + 1
FROM Person AS p
INNER JOIN Descendants_CTE AS d ON p.EmployeeId = d.ManagerId
WHERE d.IsActive = 1
)
SELECT EmployeeId, SUM(level) AS NoofDescendantsActive
FROM Descendants_CTE
WHERE level > 0
GROUP BY EmployeeId
递归遍历树“自下而上”,累计到目前为止遇到的“活动”节点的数量。如果满足非活动节点,则终止遍历。使用GROUP BY
,我们可以获得每个非叶节点下的活动节点总数。如果您还想获得其他字段,则必须JOIN
以上查询原始表格。
提示:为了更好地理解查询算法的实际效果,您可以在一张纸上构建树的图形。使用彩色标记突出显示每个活动节点。
答案 1 :(得分:2)
Giorgos的solution有一个缺陷。如果员工#6是made active,则经理#1应该仅增加1。但是,在他的解决方案中,它增加了2。
EmployeeId NoofDescendantsActive
1 6
2 4
3 2
4 2
9 1
这是一个有效的解决方案:
with Managers as
(
select
RootManagerId = EmployeeId, IsActive
from dbo.Person
where EmployeeId in (select ManagerId from dbo.Person where IsActive = 1)
),
A as -- Manager with employees
(
select m.RootManagerId, AnchorManagerId = m.RootManagerId,
ManagerId = convert(int, null)
from Managers m
union all
select m.RootManagerId, AnchorManagerId = d.EmployeeId,
d.ManagerId
from A m
-- collect descendants
join dbo.Person d on m.AnchorManagerId = d.ManagerId and d.IsActive = 1
),
Solution as
(
select RootManagerId, count(*) as Descendants
from A
where ManagerId is not null
group by RootManagerId
)
-- select * from A order by RootManagerId; -- Uncomment to see how things works
select * from Solution;
RootManagerId Descendants
1 4
2 3
3 2
4 2
9 1
如果员工#6处于活动状态,则为result:
RootManagerId Descendants
1 5
2 4
3 2
4 2
9 1