【问题标题】:Find All employees reporting to manager, including managers employees查找所有向经理汇报的员工,包括经理员工
【发布时间】:2015-08-20 07:42:31
【问题描述】:

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

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

    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

(案例陈述是因为最高管理者有主管领域向自己汇报)

我一直在寻找的是能够为这个查询提供一个 emblid 并一直看到向该经理报告的员工的能力。在我的两个示例中,我觉得我可以看到直接下属,但不知何故,我应该再次加入以查看其余信息。

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

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

【问题讨论】:

    标签: sql sql-server-2008 tsql sql-server-2012 recursive-cte


    【解决方案1】:

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

    连接查询将被限制为每个连接一个级别(尝试添加一个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 
    

    【讨论】:

    • 这并没有完全按原样工作,如果我错了,请纠正我,但以“cte as...”开头,我认为 where [supervisor_id] is null and [emplid] = 1 的 where 子句应该是只是WHERE [emplid] = 1
    • 酷,谢谢@jpw!
    • 我一直在尝试遵循您的代码,以便了解它在做什么,这似乎是一个常规递归 CTE,但使用 WHERE 子句,您选择了 CTE 的起点工作顺利吗?试图弄清楚@jpw让我头疼
    • @JasonR。这是常规递归,where 子句就像你说的那样定义了起点。递归可能很难理解,这篇文章很好地解释了它:technet.microsoft.com/en-us/library/…
    猜你喜欢
    • 2013-05-28
    • 1970-01-01
    • 1970-01-01
    • 2020-03-12
    • 2021-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-18
    相关资源
    最近更新 更多