2017-04-17 22 views
0

にリレーショナルテーブル内に捕捉ツリー内のすべてのノードを収集:は、私は次のスキーマを持つテーブルを持っているSQL Serverの

あなたが見ることができるように
CREATE TABLE Feature 
(
    FeatureId INT IDENTITY(1,1), 
    ParentFeatureId INT, 
    TargetObjectType VARCHAR(64) 
) 

が、それは機能のツリーを定義します。私は、特定のノードの下にあるすべての子孫を収集することに興味があります。

私の現在のソリューションは、私にはかなり厄介なようだ:

IF OBJECT_ID('tempdb..#features') IS NOT NULL 
    DROP TABLE #features 

SELECT 
    0 FeatureId, TargetObjectType, ParentFeatureID 
INTO 
    #features 
FROM 
    Feature 
WHERE 
    1 = 0 

INSERT INTO #features 
    SELECT 
     FeatureId, TargetObjectType, ParentFeatureID 
    FROM 
     Feature 
    WHERE 
     TargetObjectType IN ('Root1', 'Root2') 

WHILE @@ROWCOUNT > 0 
    INSERT INTO #features 
     SELECT FeatureId, TargetObjectType, ParentFeatureID 
     FROM Feature f 
     WHERE ParentFeatureID IN (SELECT FeatureId FROM #features) 
      AND NOT EXISTS (SELECT 1 FROM #features WHERE FeatureId = f.FeatureId) 

SELECT * FROM #features 

はそれを行うためのよりエレガントな方法はありますか?おそらく再帰的なCTEを使用していますか?

データ量は重要ではありません(最大で数千レコード)。すべてのデータは、階層レベルがほんの少し、たとえば最大7つのフォレストを表します。

+0

はい再帰CTEは、おそらくここでの最良の選択肢であるWHERE e.FeatureId = @lookupFeatureIdするCTEの最初のselect文でWHERE句を変更します。 –

+0

再帰CTEの作成についてのヘルプが必要な場合は、http://stackoverflow.com/questions/18106947/cte-recursion-to-get-tree-hierarchyをご覧ください。 –

答えて

0

ここでは、上部にパラメータとして渡すFeatureIdの子ノードを与える再帰的なCTEがあります。あなたは子供だけをしたい場合は、WHERE e.ParentFeatureId = @lookupFeatureId代わりの

DECLARE @lookupFeatureId INT; SET @lookupFeatureId = 6; 

WITH cte (FeatureId, ParentFeatureId, TargetObjectType, [Level]) 
AS 
(
    SELECT e.FeatureId, e.ParentFeatureId, e.TargetObjectType, 0 AS Level 
    FROM Feature AS e 
    WHERE e.FeatureId = @lookupFeatureId 

    UNION ALL 

    SELECT e.FeatureId, e.ParentFeatureId, e.TargetObjectType, d.[Level] + 1 
    FROM Feature AS e 
    INNER JOIN cte AS d 
    ON e.ParentFeatureId = d.FeatureId 
) 
SELECT FeatureId, ParentFeatureId, TargetObjectType, [Level] 
FROM cte 
関連する問題