1

設定 :

MyTable (
    NodeId varchar(10),
    ParentNodeId varchar(10),
    NodeName varchar(50)
)

NodeId は数値ではなく、任意の形式を取ることができます。大部分は Z123456 の形式ですが、一部は 12345 です。

階層的なニーズに合わせて SqlServer HierarchyId データ型を使用したいと考えています。

問題:

CTE を使用してノードと親を含む階層を生成できますが、hierarchyid::Parse() に渡すパスが必要です - 残念ながら、Z123456 形式のノード ID は解析されません。NodeId と ParentNodeId が行 ID の整数である場合、荷物をまとめて家に帰る電車に乗って素敵な妻に会いますが、代わりに、ここで 3360 x 1050 の解像度を見つめています。

CTE を使用して階層を生成しています (また、CTE 内にパスを作成することもできます)。その後、行番号を付けて一意の整数 ID を取得しますが、階層 CTE を再実行する必要があります。生成された ID を使用してパスを生成します。

;with o as (
    select n.ParentNodeID, n.nodeid, n.NodeName, 1 as [level]
    from Mytable n where n.ParentNodeID is null
        union all
    select n.ParentNodeID, n.nodeid, n.NodeName, o.[level] + 1 as [Level]
    from MyTable n inner join o on n.ParentNodeID = o.NodeID
) 
select NodeID, ParentNodeID, NodeDescription
     , ROW_NUMBER() over (order by [level]) as hNodeId 
from o

質問 :

とにかく、hierarchyId::Parse() が 1 つの CTE で受け入れるフォームでパスを達成できますか? 例 /1/2/3/

ティア

4

1 に答える 1

3
with C as
(
  select T.NodeId,
         T.ParentNodeId,
         cast('/'+cast(row_number() over(order by T.NodeId) as varchar(10)) as varchar(max)) as HID
  from MyTable as T
  where T.ParentNodeId is null
  union all
  select T.NodeId,
         T.ParentNodeId,
         C.HID+'/'+cast(row_number() over(order by T.NodeId) as varchar(10))
  from MyTable as T
    inner join C 
      on T.ParentNodeId = C.NodeId
)
select NodeId,
       ParentNodeId,
       HID,
       hierarchyId::Parse(HID+'/') 
from C
order by HID

SQLフィドル

更新:
ちょっとした調査によると、再帰 CTE で分析関数を使用することは許可されていません。私のテストでは機能しますが、別の解決策が考えられる場合は、この回答を更新します。

CTE の分析関数と集計関数に関する省略

更新 2:
MSDN に記載されているため、このソリューションは安全に使用できるようです。
WITH common_table_expression (Transact-SQL)

CTE の再帰部分の分析関数と集計関数は、CTE のセットではなく、現在の再帰レベルのセットに適用されます。ROW_NUMBER などの関数は、CTE の再帰部分に渡されたデータ セット全体ではなく、現在の再帰レベルによって渡されたデータのサブセットに対してのみ動作します。

于 2012-07-05T14:20:03.753 に答える