1

我有一张桌子(见图)员工(经理是另一个经理,依此类推),id、parentid、salary、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 ;

这是我的员工测试表

4

2 回答 2

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
于 2012-06-05T12:26:27.750 回答
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

然后更改Employees表,使用以下函数将TotalSalary列更改为计算列:

dbo.fn_TotalSalary(EmployeeId)

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

select * from Employees

获取详细信息。这样做意味着您的数据始终是 100% 准确和最新的,而不是潜在地检索过时的数据。

于 2012-06-05T12:52:30.550 回答