私は2つのアプローチを考えることができます。
1)必要以上の行を生成しますが、繰り返しが深すぎないことを確認するためのチェックを含めます。次に、重複するユーザーレコードを削除します。
2)文字列を使用して、すでにアクセスしたユーザーを保持します。うまくいかなかったサブクエリにないアイデアのように。
アプローチ1:
; with TooMuchHierarchy as (
select "User_ID"
, Manager_ID
, 0 as Depth
from "User"
WHERE "User_ID" = @UserID
union all
select U."User_ID"
, U.Manager_ID
, M.Depth + 1 as Depth
from TooMuchHierarchy M
inner join "User" U
on U.Manager_ID = M."user_id"
where Depth < 100) -- Warning MAGIC NUMBER!!
, AddMaxDepth as (
select "User_ID"
, Manager_id
, Depth
, max(depth) over (partition by "User_ID") as MaxDepth
from TooMuchHierarchy)
select "user_id", Manager_Id
from AddMaxDepth
where Depth = MaxDepth
この線where Depth < 100
は、最大再帰エラーが発生しないようにするものです。この数を少なくすると、破棄する必要のあるレコードが少なくなります。小さすぎると従業員が戻らないので、少なくとも保存されている組織図の深さと同じ大きさであることを確認してください。会社が成長するにつれ、ちょっとしたメンテナンスの悪夢。より大きくする必要がある場合は、option (maxrecursion ... number ...)
全体に追加して、より多くの再帰を許可します。
アプローチ2:
; with Hierarchy as (
select "User_ID"
, Manager_ID
, '#' + cast("user_id" as varchar(max)) + '#' as user_id_list
from "User"
WHERE "User_ID" = @UserID
union all
select U."User_ID"
, U.Manager_ID
, M.user_id_list + '#' + cast(U."user_id" as varchar(max)) + '#' as user_id_list
from Hierarchy M
inner join "User" U
on U.Manager_ID = M."user_id"
where user_id_list not like '%#' + cast(U."User_id" as varchar(max)) + '#%')
select "user_id", Manager_Id
from Hierarchy