1

EMPLID、NAME、SUPERVISOR_ID の少なくとも 3 つの列を含むテーブルがあります。単一のクエリで、マネージャーの直属の部下を取得したいと思います。これには、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

(ケースステートメントは、最高のマネージャーが自分自身に報告するスーパーバイザーフィールドを持っているためです)

私が探していたのは、このクエリに emplid を与え、そのマネージャーに報告するスタッフまでずっと見ることができる機能でした。私の 2 つの例では、直属の部下を見ることができるように感じますが、残りの情報を見るには別の結合を行う必要があります。

そして、関連する2番目の質問ですが、これを調査している間、ほとんどの人は、それ自体に結合された最初のクエリを使用して解決できたと思うときに、再帰cteを使用してマネージャーの直属の部下を見つけることを解決しているようです。私が投稿した 2 つのクエリを考えると、それ自体に結合された同じテーブルを使用できるのに、なぜ再帰 CTE を使用して解決するのでしょうか? 同じ情報が返ってきたような?

それが何かを意味する場合、これは SQL Server 2012 または 2008 で実行されます。

4

1 に答える 1

4

再帰を使用する理由は、アンカーとして使用されるマネージャーに再帰的に変更することにより、データをドリルダウンして、階層として出力を見つけて取得できるようにするためです。

結合クエリは、結合ごとに 1 つのレベルに制限されます (それにwhere manager.emplid = 1(またはマネージャーの ID を付けて) 追加してみて、何が起こるかを観察してください)。事前にレベル数がわかっている場合は、左結合 (レベルごとに 1 つの結合) を使用できます。

私はこれに再帰的な解決策を変更します:

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 
于 2015-08-20T08:28:59.343 に答える