2
CREATE TABLE [dbo].[Nodes](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Data] [nvarchar](50) NOT NULL,
    [ParentId] [int] NULL,
    [Position] [char](1) NULL,
    CONSTRAINT [PK_Customer] PRIMARY KEY CLUSTERED (
    [Id] ASC)
)

CREATE TABLE [dbo].[Closure](
    [ParentId] [int] NOT NULL,
    [ChildId] [int] NOT NULL,
    [PathLength] [int] NOT NULL,
    CONSTRAINT [PK_Closure] PRIMARY KEY CLUSTERED(
    [ParentId] ASC,
    [ChildId] ASC )
)

私がする必要があるのは、特定のノードに対して極右のノードを取得することです。

これを解決するためのクエリに関するヘルプはありますか?ありがとう。

4

1 に答える 1

0

仮定

  1. Nodes.Position親の下の子ノードの位置を決定し、グローバルではなく、親によって一意です。
  2. の値はNodes.Positionハードコードされておらず、事前にわかっていません。
  3. で並べ替えるNodes.Positionと、最初のアイテムが左のアイテム、最後のアイテムが右のアイテムになります。
  4. 極端なノードの定義は、ノードの左端または右端の子を取得することによって取得されるノードであるということです。

解決

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)

あなたのコンテキストでクロージャーアプローチが入れ子になったセットよりも理にかなっているのかどうかはわかりませんが、このクエリの目的では、違いは非常に劇的です。

于 2012-12-04T12:11:03.203 に答える