2012-06-05 59 views
1

我有一张表(请参阅图像)员工(经理是另一个人的经理等等),ID为id,parentid,薪水,totalsalary。最后一个需要更新,以便每个员工都有其子孙工资总和。我已经编写了脚本,它可以通过id获得总薪水,并且可以更新游标中的列,但是它很重要...还有其他方法吗?递归更新管理器表树

DECLARE @id INT ; 
DECLARE @s INT ; 
DECLARE curs CURSOR FOR 
SELECT personid FROM dbo.Employees 
OPEN curs ; 
FETCH NEXT FROM curs INTO @id ; 
WHILE @@FETCH_STATUS = 0 
    BEGIN 
     WITH Xemps (ID) 
        AS (SELECT PersonID AS ID 
         FROM  dbo.Employees 
         WHERE PersonID = @id 
         UNION ALL 
         SELECT e.PersonID AS ID 
         FROM  dbo.Employees AS e 
           INNER JOIN Xemps AS x ON e.ManagerID = x.ID 
        ) 
      SELECT @s = SUM(Salary) 
      FROM dbo.Employees 
      WHERE PersonID IN (SELECT id 
            FROM  Xemps) 
     UPDATE dbo.Employees 
     SET  SalarySum = @s 
     WHERE PersonID = @id 
     FETCH NEXT FROM curs INTO @id 
    END 
CLOSE curs ; 
DEALLOCATE curs ; 

this is my test table of Employees

+1

请标记您的SQL Server版本 – njr101

回答

4

光标是没有必要的,这是可以做到只使用一个递归公用表表达式:

WITH Emp AS 
( SELECT EmployeeID, Salary, ManagerID 
    FROM dbo.Employee 
    UNION ALL 
    SELECT e.EmployeeID, e.Salary, Emp.ManagerID 
    FROM dbo.Employee e 
      INNER JOIN Emp 
       ON e.ManagerID = Emp.EmployeeID 
) 
UPDATE dbo.Employee 
SET  SalarySum = COALESCE(s.Salary, 0) + e.Salary 
FROM dbo.Employee e 
     LEFT JOIN 
     ( SELECT ManagerID, SUM(Salary) [Salary] 
      FROM Emp 
      GROUP BY ManagerID 
     ) s 
      ON s.ManagerID = e.EmployeeID 
1

创建执行用于每个在那里它们是雇员之和的函数一个经理:

create function dbo.fn_TotalSalary  
{ 
    @EmployeeId int 
} 
returns float 
as 
begin 

    declare @totalSalary float 

    select @totalSalary = sum(salary) 
    from dbo.employees 
    where employeeid = @employeeid or managerid = @employeeid 

    return @totalSalary 
end 

然后改变雇员表,使用该函数将TotalSalary列更改为计算列:

dbo.fn_TotalSalary(EmployeeId) 

随着员工收入增加,计算列将自动更新。然后您可以简单地致电

select * from Employees 

以获取详细信息。这样做会意味着您的数据始终是100%准确且最新的,而不是可能检索陈旧的数据。