查找向经理报告的所有员工,包括经理员工

Find All employees reporting to manager, including managers employees

我有一个 table 至少包含三列,EMPLID、NAME、SUPERVISOR_ID。在单个查询中,当在 WHERE 子句中给出 managersid 时,我希望获得经理的直接报告,包括从下属经理一直到最低员工的任何直接报告。

我可以创建一个查询来显示谁向谁报告:

    SELECT MANAGER.[EMPLID] AS MANAGEREMPLID, MANAGER.[NAME], MANAGER.[SUPERVISOR_ID], STAFF.[EMPLID] AS STAFFEMPLID, STAFF.[NAME], STAFF.[SUPERVISOR_ID]  
  FROM MYHRTABLE AS MANAGER INNER JOIN MYHRTABLE AS STAFF
  ON MANAGER.[EMPLID] = STAFF.[SUPERVISOR_ID]
  ORDER BY MANAGER.[NAME], STAFF.[NAME]

或看似做同样事情的递归 CTE

 WITH MYCTE
AS ( 
SELECT [EMPLID], [NAME],[SUPERVISOR_ID] FROM 
    (SELECT [EMPLID], [NAME], 
        CASE WHEN [EMPLID] = [SUPERVISOR_ID] THEN NULL ELSE [SUPERVISOR_ID] END AS [SUPERVISOR_ID]              
    FROM MYHRTABLE) AS MYDATA
        WHERE [SUPERVISOR_ID] IS NULL

UNION ALL

    SELECT MYDATA.[EMPLID], MYDATA.[NAME],MYDATA.[SUPERVISOR_ID] FROM 
    (SELECT [EMPLID], [NAME], 
        CASE WHEN [EMPLID] = [SUPERVISOR_ID] THEN NULL ELSE [SUPERVISOR_ID] END AS [SUPERVISOR_ID]      
    FROM MYHRTABLE) AS MYDATA INNER JOIN MYCTE ON MYDATA.[SUPERVISOR_ID] = MyCTE.[EMPLID]
    WHERE MYDATA.[SUPERVISOR_ID] IS NOT NULL)
SELECT * FROM MyCTE

(case语句是因为最高管理者有supervisor字段向自己汇报)

我一直在寻找的是能够使这个查询变得简单,并一直查看向该经理报告的员工。在我的两个示例中,我觉得我可以看到直接报告,但我应该以某种方式进行另一个连接以查看其余信息。

第二个问题有点相关,在研究这个问题时,似乎大多数人都使用递归 cte 解决了寻找经理直接下属的问题,而我认为它可以使用连接到自身的第一个查询来解决。鉴于我发布的两个查询,当我可以使用相同的 table 连接到自身时,为什么我要使用递归 CTE 来解决它?好像我得到了相同的信息?

如果有任何意义,这将是 运行 在 SQL Server 2012 或 2008 上。

您使用递归的原因是能够通过递归更改为用作锚点的管理器来向下钻取数据,直到没有更多内容可查找并获取输出作为层次结构。

连接查询将被限制为每个连接的一个级别(尝试向其添加 where manager.emplid = 1(或 w/e 经理的 ID)并观察会发生什么)。如果您事先知道级别数,则可以使用左联接(每个级别一个联接)。

我会改变递归解决方案:

with src as (
  select 
    [emplid]
    , [name]
    , case 
        when [emplid] = [supervisor_id] then null 
        else [supervisor_id] 
     end as [supervisor_id]
  from myhrtable
), cte as ( 
  select [emplid], [name], [supervisor_id], [emplid] as top_manager
  from src
  where [emplid] = 1 -- this is the manager you're interested in
                     -- it can be a sub-manager in the middle or the tree
union all            -- or the top level manager rooting the tree

  select src.[emplid], src.[name], src.[supervisor_id], top_manager
  from src 
  inner join cte on src.[supervisor_id] = cte.[emplid]
  where src.[emplid] <> top_manager
)

select * from cte