recursive sql function with rollup logic?

后端 未结 3 857
感情败类
感情败类 2021-01-28 23:33

i have a SQL that using a recursive CTE to expand a self-referancing employees table builds a result set of defects aggregated by user and severity level.

here is my CTE

3条回答
  •  耶瑟儿~
    2021-01-29 00:19

    This isn't tested as I don't have a mssql install here nor your data, but, I think it should be generally right and at least push you in a useful direction.

    First, you need to change the query in your UDF to give two additional pieces of information. The "topmost" employee for your aggregation collapsing (which I think you said is the first direct report, not the very top employee), and the overall depth. As such:

    WITH yourcte AS  
      (  
        SELECT EmployeeId, ManagerNTID, ManagerID, NTID, FullName, 0 as Depth, ntid as Topmost  
        FROM Employees  
        WHERE NTID = @NTID
        UNION ALL  
        SELECT e.EmployeeId, e.ManagerNTID, e.ManagerID, e.NTID, e.FullName, y.Depth+1, case when y.depth = 0 then e.ntid else y.Topmost end
        FROM Employees e  
        JOIN yourcte y ON e.ManagerNTID = y.NTID
      )  
    SELECT EmployeeId, ManagerID, NTID, FullName, Depth, Topmost  
    FROM yourcte
    

    Then, your actual query needs a few extra details to extract that information and use it

    SELECT 
      e.FullName, 
      Urgent, 
      High, 
      Medium, 
      Low
    FROM fnGetEmployeeHierarchyByUsername ('ssalvati') e
    LEFT OUTER JOIN(
        SELECT [AssignedTo],
               SUM([1-Urgent]) AS Urgent,
               SUM([2-High]) AS High,
               SUM([3-Medium]) AS Medium,
               SUM([4-Low]) AS Low
          FROM (SELECT [AssignedTo],[BusinessSeverity] FROM Defects WHERE Status <> 'Closed') D
          join fnGetEmployeeHierarchyByUsername ('ssalvati') e2 on d.AssignedTo = e2.ntid
         PIVOT (COUNT([BusinessSeverity]) FOR [BusinessSeverity] IN ([1-Urgent],[2-High],[3-Medium],[4-Low])) V
         where e2.TopMost = e.ntid
        GROUP BY [AssignedTo]) AS def
    ON e.ntid = def.[AssignedTo]
    where e.Depth <= 1
    

    The double call to your UDF might be a bit expensive, so you may want to consider putting this into a sproc and using a temp table to catch the results of the UDF to join against.

    Also note that the UDF could take an extra parameter as to how deep "topmost" is, making this more general that it currently is in its hardcoded form.

提交回复
热议问题