2016-10-15 11 views
3

親の関係を持つツリー内のノードを識別するためのクエリがあります。このクエリで何が問題になっていますか?内部ノードがあっても、対応するcase文は決して実行されません。常にリーフノードまたはルートノードとして結果が得られます。アウトプットでインナーを決してしないでください。私はおそらく何が間違っているのでしょうか?SQL CASEステートメント固有の例

WITH CTE(N, P, [Level]) 
AS 
(
    SELECT N, P, 1 FROM 
    BST B 
    WHERE P IS NULL 
    UNION ALL 
    SELECT B.N, B.P, [Level] + 1 FROM 
    BST B 
    JOIN CTE ON B.P = CTE.N 
) 
SELECT N, 
CASE 
WHEN [Level] = 1 Then 'Root' 
WHEN [Level] < MAX([Level]) AND [Level] > 1 THEN 'Inner' 
WHEN [Level] = MAX([Level]) THEN 'Leaf' 
END 
FROM CTE 
GROUP BY N, [Level] 
ORDER BY N ASC; 

サンプル入力

N P 
1 2 
3 2 
6 8 
9 8 
2 5 
8 5 
5 NULL 

サンプル出力

1 Leaf 
2 Inner 
3 Leaf 
5 Root 
6 Leaf 
8 Inner 
9 Leaf 
+0

ですか –

答えて

4

なぜハイアールを構築するのですか?ちょうどメモ、これがギザギザの階層である場合、最大(レベル)は必ずしも機能しません。例えば、我々は問題を再現できるように、あなたにもいくつかのサンプルデータを投稿することができますか?リーフ・ノードは、レベル3であるが、最大レベルは6

Declare @YourTable table (N int,P int) 
Insert Into @YourTable values 
(1, 2), 
(3, 2), 
(6, 8), 
(9, 8), 
(2, 5), 
(8, 5), 
(5, NULL) 

Select A.* 
     ,Lvl = case when A.P is null then 'Root' else case when B.P is null then 'Leaf' else 'Inner' end end 
From @YourTable A 
Left Join (Select Distinct P from @YourTable) B on A.N=B.P 

戻り

N P Lvl 
1 2 Leaf 
3 2 Leaf 
6 8 Leaf 
9 8 Leaf 
2 5 Inner 
8 5 Inner 
5 NULL Root 
1

あなたはあなたがすべてのレコードのうち、maxレベルを得ることはありませんGroup bylevelを追加した

あなたはここに

Max Over()ウィンドウ集計関数を使用してこれを行うことができます一つの方法

SELECT N, 
     CASE 
     WHEN [Level] = 1 THEN 'Root' 
     WHEN [Level] < Max([Level]) over() 
       AND [Level] > 1 THEN 'Inner' 
     WHEN [Level] = Max([Level]) over() THEN 'Leaf' 
     END 
FROM CTE 
ORDER BY N ASC; 
+0

優れています。説明ありがとう。 – ckv

2

は、あなたが次のクエリを使用することができます:アイデアは、ルートノードを伝播することである

WITH CTE(N, P, [Level]) 
AS 
(
    SELECT N AS Node, N AS P, 1 as Level 
    FROM BST B 
    WHERE P IS NULL 

    UNION ALL 

    -- Propagate parent to all subsequent nodes 
    SELECT B.N, CTE.P, Level = [Level] + 1 
    FROM BST B 
    JOIN CTE ON B.P = CTE.N 
) 
SELECT N, 
     CASE 
      WHEN [Level] = 1 THEN 'Root' 
      WHEN [Level] > 1 AND [Level] < MAX([Level]) OVER (PARTITION BY P) THEN 'Inner' 
      WHEN [Level] = MAX([Level]) OVER (PARTITION BY P) THEN 'Leaf' 
     END 
FROM CTE  
ORDER BY N ASC; 

を他のすべてのノードにダウンして、MAXのウィンドウ版を親ノード節でパーティションに適用することができます。

Demo here

関連する問題