我可以想到两种方法。
1)产生比你想要的更多的行,但包括一个检查以确保它不会递归太深。然后删除重复的用户记录。
2)使用字符串来保存已经访问过的用户。就像不工作的子查询中的想法一样。
方法一:
; 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 ...)
到整个事物以允许更多递归。
方法二:
; 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