2011-01-04 17 views
0

私はグループのパスのようなパン粉​​を生成する必要があります特定の連絡先CTE - 逆階層

T_GROUP店グループの実際の階層:連絡先に属する

GROUP_ID NAME   PARENT_ID LEVEL 
    7  g1    NULL   1 
    80 Workgroups  7   2 
    82 Advocacy  80   3 

T_CONTACT_GROUPテーブルにはグループ:

CONTACT_ID GROUP_ID 
55   82 
56   7 
55   7 

今は、私は連絡先ID 55ためを次のように結果セットを取得したいと思います:連絡先55にもグループ7が割り当てられているため、期待される結果セットでg1が2回来たことに注意してください。

contactId GROUP_ID NAME PARENT_ID LEVEL 
55  7  g1  NULL  1 
55  80  g1|Workgroups 7 2 
55  82  g1|Workgroups|Advocacy 80 3 
55  7   g1 NULL 1 

答えて

2

少なくとも2つの方法があります。 あなたはあなたのタイトルにCTEを書いていますので、まずそれを見て行きます。リンクhereから 私はhiererchical CTE、少しマッサージの例を持って、それはむしろ子供より親を表します

WITH Hierarchy (Group_ID, Name, Parent_ID, Level) AS 
(
    SELECT Group_ID, Name, Parent_ID, Level 
    FROM T_Group 
    WHERE Contact_id = @Leaf 
UNION ALL 
    SELECT g.Group_ID, g.Name, g.Parent_ID, g.Level 
    FROM T_Group g 
    INNER JOIN Hierarchy h ON g.Group_ID = h.Parent 
) 

このCTEは取って、ストアドプロシージャまたはテーブルユーザー定義関数に配置されます@Leaf(あなたの探している葉のノード。あなたの例では82と7です)のパラメータです。

この問題は、階層的なCTEが、より深いツリー構造で作業したり、繰り返し呼び出されたりする場合、非常に高価になる可能性があることにあります。キャッシングは役に立ちますが、他にもオプションがあります。

もう一つの方法は、あなたのグループと一緒に文字列連結フィールドに親の階層を格納することです:すべての詳細を取得する

SELECT p.Group_ID, g.Name, g.Parent_ID, g.Level 
FROM T_GROUP g 
CROSS JOIN dbo.StringSplit('|', Parents) p 
WHERE p.Value = g.Group_ID 

GROUP_ID NAME  PARENT_ID LEVEL PARENTS 
82  Advocacy 80  3  |7|80|82| 

それからような何かを行うことができます親。これは、ルックアップの処理にCTEを使用するよりもはるかに効率的な傾向があります。つまり、新しいレコードをGROUPに挿入すると、親フィールドも作成する必要があります。通常これを処理するには、グループを作成し、必要に応じて親を構築するストアドプロシージャを作成します。