仮定
Nodes.Position
親の下の子ノードの位置を決定し、グローバルではなく、親によって一意です。
- の値は
Nodes.Position
ハードコードされておらず、事前にわかっていません。
- で並べ替える
Nodes.Position
と、最初のアイテムが左のアイテム、最後のアイテムが右のアイテムになります。
- 極端なノードの定義は、ノードの左端または右端の子を取得することによって取得されるノードであるということです。
解決
dbo.Nodes
解決策は、ツリーの深さ優先のトラバースがクロージャー テーブルでより簡単になる解決策を見つけることができなかったため、使用するだけであり、シナリオでは重要なPosition
列が ondbo.Nodes
です。親 ID と子 ID を取りdbo.Closure
、結合しdbo.Nodes
て取得することもできますが、それではPosition
不要な結合が追加されるだけです。
以下のクエリは、一番右のノードに対するものです。左のノードを見つけるには、並べ替えを に変更しASC
ます。
;WITH
RecCTE AS
(
SELECT
Id,
1 AS NodeLevel
FROM
(
SELECT
N.Id,
ROW_NUMBER() OVER (PARTITION BY N.ParentId ORDER BY N.Position DESC) AS NodeRank
FROM
dbo.Nodes AS N
WHERE
N.ParentId = @Parent
) AS SQ
WHERE
NodeRank = 1
UNION ALL
SELECT
Id,
NodeLevel + 1 AS NodeLevel
FROM
(
SELECT
N.Id,
R.NodeLevel,
ROW_NUMBER() OVER (PARTITION BY N.ParentId ORDER BY N.Position DESC) AS NodeRank
FROM
dbo.Nodes AS N
INNER JOIN RecCTE AS R ON N.ParentId = R.Id
) AS SQ
WHERE
NodeRank = 1
)
SELECT
Id
FROM
RecCTE
WHERE
NodeLevel IN ( SELECT MAX(NodeLevel) FROM RecCTE )
更新: ネストされたセットのソリューション
テーブル構造の変更を受け入れる場合は、このシナリオのネストされたセットのアプローチを検討することをお勧めします。たとえば、次のテーブルがあるとします (ノード位置に関して入力されます)。
CREATE TABLE [dbo].NestedSets
(
Id int NOT NULL PRIMARY KEY CLUSTERED,
LeftNum int NOT NULL,
RightNum int NOT NULL,
PathLength int NOT NULL
)
次に、左端のノードを見つけるのは次のように簡単です
SELECT
C.Id
FROM
dbo.NestedSets AS C
INNER JOIN dbo.NestedSets AS P
ON P.LeftNum < C.LeftNum AND P.RightNum > C.RightNum
WHERE
P.Id = @Parent
AND C.LeftNum = C.RightNum - 1
AND C.LeftNum = P.LeftNum + C.PathLength - P.PathLength
一番右のノード:
SELECT
C.Id
FROM
dbo.NestedSets AS C
INNER JOIN dbo.NestedSets AS P
ON P.LeftNum < C.LeftNum AND P.RightNum > C.RightNum
WHERE
P.Id = @Parent
AND C.LeftNum = C.RightNum - 1
AND C.RightNum = P.RightNum - (C.PathLength - P.PathLength)
あなたのコンテキストでクロージャーアプローチが入れ子になったセットよりも理にかなっているのかどうかはわかりませんが、このクエリの目的では、違いは非常に劇的です。