質問

自己参照テーブルを指定

Item 
-------------
Id (pk)
ParentId (fk)

関連する値の関連テーブルを使用

ItemValue
-------------
ItemId (fk)
Amount

そしていくつかのサンプルデータ

Item                       ItemValues 
Id      ParentId           ItemId      Amount
--------------------       ----------------------
1       null               1           10
2       1                  3           40
3       1                  3           20
4       2                  4           10
5       2                  5           30
6       null
7       6
8       7

Item.Id を取得し、すべての ItemValue.Amounts の合計を直接の子に返すために、sprocが必要です。木の下。

たとえば、 1 が渡された場合、ツリーは 2、3、4、5 になり、直接の子は 2、3 出力は次のようになります

 ItemId    Amount
 ------------------
 2         40     (values from ItemIds 4 & 5)
 3         60     (values from ItemId 3)

この動作を実現するには、どのようなアプローチを適用する必要がありますか?

CTEの使用を検討していますが、より良い/より速いアプローチがあるかどうか疑問に思っています。

役に立ちましたか?

解決

階層が深くなりすぎないと仮定すると、このような再帰CTEが機能します。

declare @ParentId int;
set @ParentId = 1;

;with 
  Recurse as (
    select 
      a.Id as DirectChildId
    , a.Id
    from Item a 
    where ParentId = @ParentId
    union all
    select
      b.DirectChildId
    , a.Id
    from Item a 
    join Recurse b on b.Id = a.ParentId
    )
select
  a.DirectChildId, sum(b.Amount) as Amount
from Recurse a
left join ItemValues b on a.Id = b.ItemId
group by
  DirectChildId;

非CTEメソッドでは、カーソルベースなどの何らかの形の反復が必要になります。それはストアドプロシージャであり、可能性があり、再帰するデータがたくさんある場合、データを適切にスライスする限り、おそらくより良いスケーリングになります。

クラスター化インデックスがIdにある場合、ParentIdに非クラスター化インデックスを追加します。カバリングインデックスとして、ブックマークルックアップなしで初期シークを満たします。クラスター化インデックスは、再帰的な結合に役立ちます。

クラスター化インデックスが既にParentIdにある場合は、Idに非クラスター化インデックスを追加します。一緒に、それらは実質的に上記と同等になります。 ItemValuesの場合、実際のテーブルがこれよりも広い場合、(ItemId)INCLUDE(Amount)のインデックスが必要になる場合があります。

他のヒント

ネストされたセットモデルのようにデータを保存できますか(これはMySQL 参照が、アイデアはデータベース全体で一般的です)?もしそうなら、あなたが探している値を見つけるための操作はかなり簡単でしょう。

これはデータベースで処理する必要がありますか?必要なデータをBLLに取り込み、そこで再帰を実行することをお勧めします。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top