SQL CASE语句特定示例

时间:2016-10-15 16:43:58

标签: sql sql-server

我有一个查询,用于识别具有父关系的树中的节点。这个查询有什么问题?即使我有内部节点,也不会执行相应的case语句。我总是以Leaf或Root节点获得结果。永远不要在输出中获得内心。我可能做错了什么?

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

3 个答案:

答案 0 :(得分:4)

Why build the hier? Just a note, if this is a Jagged Hierarchy, the Max(Level) will not necessarily work. For example, a leaf node is a level 3 but the max level is 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

Returns

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 :(得分:2)

You can use the following query:

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;

The idea is to propagate the root node down to all other nodes, so that we can apply windowed version of MAX with a partition by parent node clause.

Demo here

答案 2 :(得分:1)

您已在level中添加了Group by,因此您无法从所有记录中获得max级别

您可以使用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;