Tsql 通过递归更新管理器表树

Tsql 通过递归更新管理器表树,tsql,recursion,sql-server-2008-r2,sum,with-statement,Tsql,Recursion,Sql Server 2008 R2,Sum,With Statement,我有一个员工表(见图)(经理是另一个的经理,以此类推),表中有id、parentid、salary、totalsalary。最后一个需要更新,以便每个员工都有自己的工资总额。我已经写了脚本,它通过id获取总工资,然后更新游标中的列,但它很重。。。还有别的办法吗 DECLARE @id INT ; DECLARE @s INT ; DECLARE curs CURSOR FOR SELECT personid FROM dbo.Employees OPEN curs ; FETCH NEXT FR

我有一个员工表(见图)(经理是另一个的经理,以此类推),表中有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 ;

光标不是必需的,只需使用递归公共表表达式即可:

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

光标不是必需的,只需使用递归公共表表达式即可:

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

创建一个函数,该函数为作为经理的每个员工执行求和:

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列更改为computed列:

dbo.fn_TotalSalary(EmployeeId)
随着员工收入的增加,计算列将自动更新。然后你就可以打电话了

select * from Employees

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

创建一个函数,为作为经理的每位员工执行求和:

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列更改为computed列:

dbo.fn_TotalSalary(EmployeeId)
随着员工收入的增加,计算列将自动更新。然后你就可以打电话了

select * from Employees

了解详情。这样做意味着您的数据始终是100%准确和最新的,而不是可能检索过时的数据。

请使用SQL Server版本标记请使用SQL Server版本标记