我在SQL Server 2005
中有关于Employee - Manager层次结构的下表。
以下是我要实现的目标
Busienss Logic:
- 有效的经理应该有一个部门
- 有效经理是层次结构中最近的经理,其中有一个部门
- 有效部门是有效经理的部门
我已经提到CTE
这样的递归方案。示例SQL SERVER – Simple Example of Recursive CTE
但我的情况比简单地找到最近的经理有更多的条件。
如何修改此CTE以获得预期结果?
QUERY
DECLARE @Emploee TABLE (EmpID INT, EmpName VARCHAR(50), Dept VARCHAR(5), Manager INT)
INSERT INTO @Emploee VALUES (1, 'A', NULL,NULL)
INSERT INTO @Emploee VALUES (2, 'B', 'D100',NULL)
INSERT INTO @Emploee VALUES (3, 'C', 'D101',2)
INSERT INTO @Emploee VALUES (4, 'D', 'D102',1)
INSERT INTO @Emploee VALUES (5, 'E', NULL,2)
INSERT INTO @Emploee VALUES (6, 'F', 'D103',5)
INSERT INTO @Emploee VALUES (7, 'G', NULL,6)
INSERT INTO @Emploee VALUES (8, 'H', 'D104',7)
SELECT *
FROM @Emploee
WHERE Manager IS NOT NULL
答案 0 :(得分:1)
WITH EmployeeManagers AS (
SELECT Employee.EmpId
,1 AS Level
,Employee.Manager
FROM @Employee AS Employee
WHERE Employee.Manager IS NOT NULL
UNION ALL
SELECT EmployeeManagers.EmpId
,Level + 1 AS Level
,Manager.Manager
FROM EmployeeManagers
INNER JOIN @Employee AS Manager
ON Manager.EmpId = EmployeeManagers.Manager
)
,EmployeeManagerDepartment AS (
SELECT EmployeeManagers.EmpId
,EmployeeManagers.Level
,EmployeeManagers.Manager
,Manager.Dept
FROM EmployeeManagers
LEFT JOIN @Employee AS Manager
ON Manager.EmpID = EmployeeManagers.Manager
)
,EffectiveManagerLevel AS (
SELECT EmpId
,MIN(Level) EffectiveLevel
FROM EmployeeManagerDepartment
WHERE Dept IS NOT NULL
GROUP BY EmpId
)
SELECT Employee.EmpID AS [Emp ID]
,Employee.EmpName AS [EmpName]
,Employee.Manager AS [Direct Manager]
,EmployeeManagerDepartment.Manager AS [EffectiveManager]
,EmployeeManagerDepartment.Dept AS [Effective Department]
FROM @Employee AS Employee
LEFT JOIN EffectiveManagerLevel
ON EffectiveManagerLevel.EmpId = Employee.EmpId
LEFT JOIN EmployeeManagerDepartment
ON EmployeeManagerDepartment.EmpId = Employee.EmpId
AND EmployeeManagerDepartment.Level = EffectiveManagerLevel.EffectiveLevel
WHERE Employee.Manager IS NOT NULL
答案 1 :(得分:1)
有可能将adrianm答案的CTE从3减少到2,将有效管理者的数据全部合在一起
WITH EmployeeManagers AS (
SELECT e.EmpId, e.EmpName, 1 AS Level
, e.Manager, e.EmpID CurrLevelEmpID, Cast(Null as VarChar(5)) Dept
FROM Employee AS e
WHERE e.Manager IS NOT NULL
UNION ALL
SELECT em.EmpId, em.EmpName, Level + 1 AS Level
, e.Manager, e.EmpID CurrLevelEmpID, e.Dept Dept
FROM EmployeeManagers em
INNER JOIN Employee e ON e.EmpId = em.Manager
), EffectiveManagers AS (
SELECT EmpID
, CurrLevelEmpID Manager
, Dept
, Effective = ROW_NUMBER() OVER (PARTITION BY EmpID ORDER BY Level)
FROM EmployeeManagers e
WHERE DEPT is not null
)
SELECT e.EmpID
, e.EmpName
, e.Manager
, eem.Manager EffectiveManager
, eem.Dept EffectiveDepartment
FROM Employee e
LEFT JOIN EffectiveManagers eem ON e.EmpID = eem.EmpID
AND eem.Effective = 1
WHERE e.Manager IS NOT NULL
EmployeeManagers
CTE获取更多数据,特别是CurrLevelEmpID
是当前级别员工的EmpID
,更改e.Manager
的定义将会进入定期CTE的方式,Dept
是当前级别员工的部门(如果有)。
EffectiveManagers
CTE为每位员工提供一个有效经理行,Effective
计算员工行有效经理的级别。
主查询JOIN
基表与EffectiveManagers
只获得每个层次结构的第一个(有效值为1的那个)