我有一个 SQL Server 数据库,其中的 Employee 表包含以下结构:
CREATE TABLE Employee (
EmployeeID INT PRIMARY KEY,
ManagerID INT,
EmployeeName NVARCHAR(50),
Salary DECIMAL(18, 2));
我使用递归通用表表达式(CTE)来计算每个员工及其下属的总工资。但是,当员工数量较多时,查询性能会变得很慢。
WITH RecursiveSalaryCTE AS (
SELECT EmployeeID, ManagerID, EmployeeName, Salary
FROM Employee
WHERE ManagerID IS NULL
UNION ALL
SELECT e.EmployeeID, e.ManagerID, e.EmployeeName, e.Salary
FROM Employee e
JOIN RecursiveSalaryCTE r ON e.ManagerID = r.EmployeeID)
SELECT EmployeeID, EmployeeName, Salary,
(SELECT SUM(Salary) FROM RecursiveSalaryCTE WHERE ManagerID = e.EmployeeID) AS TotalSubordinateSalaries
FROM RecursiveSalaryCTE e;
有没有更好的方法来优化这个查询?任何可以提供更快结果的替代方法或对查询的修改将不胜感激。
员工表的示例数据:
INSERT INTO Employee (EmployeeID, ManagerID, EmployeeName, Salary)
VALUES
(1, NULL, 'John', 10000.00),
(2, 1, 'Alice', 7500.00),
(3, 1, 'Bob', 8000.00),
-- ... more data ...
(1000, 999, 'Eve', 6000.00);
这个怎么样... https://dbfiddle.uk/NwF09y4y
--manager list
with managers as
(
select distinct ManagerID
from Employee
)
--sum sub salaries
,TotalSubordinateSalaries as
(
select ManagerID, sum(Salary) TotalSubordinateSalaries
from Employee
group by ManagerID
)
select EmployeeID, EmployeeName, Salary ,ts.TotalSubordinateSalaries
from Employee e
--identify the manager
left join managers m on m.ManagerID=e.EmployeeID
--join their subs
left join TotalSubordinateSalaries ts on ts.ManagerID = m.ManagerID
with RecursiveSalaryCTE(EmployeeID, managerid, salary, path) as (
SELECT EmployeeID, managerid, Salary, '/' || EmployeeID
FROM employee
WHERE managerid IS NULL
UNION ALL
SELECT e.EmployeeID, e.managerid, e.salary, r.path || '/' || e.EmployeeID
FROM employee e
JOIN RecursiveSalaryCTE r ON e.managerid = r.EmployeeID
)
select EmployeeID, managerid, salary, Total_all_sub,
sum(salary) over(partition by managerid) as total_same_manager
from (
select r.EmployeeID, r.managerid, r.salary,
SUM(r1.Salary) Total_all_sub
from RecursiveSalaryCTE r
join RecursiveSalaryCTE r1 on substring(r1.path,1,length(r.path)) = r.path
group by r.EmployeeID, r.managerid, r.salary
)
;
EID MID SAL TREE LVL
1 100 345 100
2 1 90 160 175
3 1 85 85 175
4 2 70 70 70