SQL ServerのWithコマンド(CTE)を使用して再帰を実現できます。
WITH MyCTE(ParentID,ID,Name,Level)
AS
(
SELECT ManagerID AS ParentID, UserID AS ID, UserName AS Name, 0 AS Level
FROM USERS U
WHERE U.ManagerID IS NULL
UNION ALL
SELECT U.ManagerID AS ParentID, U.UserID AS ID, U.UserName AS Name, H.Level+1 AS Level
FROM USERS U
INNER JOIN MyCTE H ON H.ID = U.ManagerID
)
SELECT ParentID,ID FROM MyCTE
戻り値
ParentID ID
NULL 1
1 2
1 3
2 4
私が達成したいのは、この結果セットを逆にすることです。つまり、ルートノードと最も深い子ノードを次のように反転します。
ParentID ID
NULL 4
4 2
2 1
3 1
パラメータを使用して再帰順序を決定するなど、プログラムでこれを実装する方法(できればCTEを使用する方法)を理解できませんでした。助けていただければ幸いです。
編集 :
これを少し変更して、最初のCTEの結果を一時テーブルに挿入し、別の再帰を使用して順序を逆にします( "WHERE T.ID =(SELECT MAX(ID)FROM @tmp)"は実際の状況では機能しないことを知っています。また、「レベル」列を使用して最も深いノードを特定する必要があります。この例では、これを単純化しようとしました)、
INSERT INTO @tmp
SELECT ParentID,ID,Level FROM MyCTE
WITH MyCTE2(ParentID,ID,Level)
AS
(
SELECT NULL AS ParentID, ID AS ID, 0 AS Level FROM @tmp T
WHERE T.ID = (SELECT MAX(ID) FROM @tmp)
UNION ALL
SELECT R2.ID AS ParentID, T.ParentID AS ID, R2.Level+1 FROM @tmp T
INNER JOIN MyCTE2 R2 ON R2.ID = T.ID
WHERE T.ParentID IS NOT NULL
)
元の結果(1,3ペアを削除)
ParentID ID Level
NULL 1 0
1 2 1
2 4 2
結果が逆になり、
ParentID ID Level
NULL 4 0
4 2 1
2 1 2
編集2:
私はこのようなことをしました、
SELECT TTT.ParentID,TTT.ID,TTT.Level FROM
(
SELECT ParentID,ID,Level FROM MyCTE2
UNION ALL
SELECT TT.ID AS ParentID,TT.ParentID AS ID,(SELECT Level+1 FROM @tmp WHERE ID=TT.ID)
AS Level FROM
(
SELECT ID FROM @tmp
EXCEPT
SELECT ID FROM MyCTE2
)T INNER JOIN @tmp TT ON TT.ID = T.ID
)TTT
ORDER BY TTT.Level
与える、
ParentID ID Level
NULL 4 0
4 2 1
2 1 2
3 1 2
これにはエラーが含まれている可能性がありますが、まだわかりませんが、ペア(3,1)がレベル2で正しいことを確認するために表示したかっただけですか?かなり前からこれについて考えていたので、私はいくつかのばかげた間違いをするかもしれません。