I can imagine two approaches.
1) Create more lines than you want, but enable validation to make sure it is not too deep. Then delete the duplicate user entries.
2) Use the string to store already visited users. Like not in the subquery, the idea did not work.
Approach 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
The where Depth < 100 is what prevents you from getting a maximum recursion error. Make this number smaller and fewer records will be created that need to be thrown away. Make it too small and employees will not be returned, so make sure it is no less than the depth of the org chart stored. The battle of an accompanying nightmare as the company grows. If it should be larger, add option (maxrecursion ... number ...) to everything to allow recursion.
Approach 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
source share