二叉树左下方或右下方

时间:2016-08-31 13:41:10

标签: sql sql-server binary-tree

我有一个存储二叉树的表,如下所示:

Id  ParentId Level Placement 
47   -1       0     0
23   47       1     0
86   47       1     1
5    23       2     0
29    23      2     1
68    86      2     0
8    5      3     1
31    29      3     1
67    68      3     0
.
.
.

使用MSSQL 现在,我需要得到一个给定id的BottomLeft,在这个例子中,47左下角是5 我需要得到一个给定id的右下角,在这个例子中,47右下角是86

左下或左下不是左下方的最低级别,而是左侧或右侧外侧的极端。

如何编写一个给我左下方或右上角的SQL?

左上方的位置为0,右侧为

enter image description here

2 个答案:

答案 0 :(得分:4)

注意:最后的注释用于说明完整的层次结构。

创建示范表

Declare @YourTable table (Id int,Pt int, Level int, Placement int) 
Insert Into @YourTable values 
(47,-1, 0,0),
(23,47, 1,0),
(86,47, 1,1),
(5 ,23, 2,0),
(29,23, 2,1),
(68,86, 2,0),
(8 , 5, 3,1),
(31,29, 3,1),
(67,68, 3,0)

SQL -

Declare @Top    int = null         --<<  Sets top of Hier Try 5
Declare @MaxLvl int = 99
Declare @Nest varchar(25) = '   '  --<<  Optional: Added for readability

;with cteHB (Seq,ID,Pt,Lvl,Title,Placement) as (
    Select  Seq  = cast(1000+Row_Number() over (Order by ID) as varchar(500))
           ,ID   
           ,Pt   
           ,Lvl=1
           ,Title =concat('Item ',ID)
           ,Placement 
     From   @YourTable Where (Pt=-1 and isnull(@Top,-1) =-1) or (ID=@Top and isnull(@Top,0) <>0)
     Union  All
     Select Seq  = cast(concat(cteHB.Seq,'.',1000+Row_Number() over (Order by cteCD.ID)) as varchar(500))
           ,cteCD.ID 
           ,cteCD.Pt
           ,cteHB.Lvl+1
           ,Title = concat('Item ',cteCD.ID) 
           ,cteCD.Placement
     From   @YourTable cteCD 
     Join   cteHB on cteCD.Pt = cteHB.ID and cteHB.Lvl+1<=@MaxLvl and cteCD.Placement=0)

,cteR1 as (Select Seq,ID,R1=Row_Number() over (Order By Seq) From cteHB)
,cteR2 as (Select A.Seq,A.ID,R2=Max(B.R1) From cteR1 A Join cteR1 B on (B.Seq like A.Seq+'%') Group By A.Seq,A.ID )
Select B.R1  
      ,C.R2
      ,A.ID
      ,A.Pt
      ,A.Lvl
      ,Title = Replicate(@Nest,A.Lvl) + A.Title
      ,A.Placement
 From cteHB A
 Join cteR1 B on A.ID=B.ID
 Join cteR2 C on A.ID=C.ID
 --Where R1=R2 
 Order By B.R1              

返回

R1  R2  ID  Pt  Lvl    Title                Placement
1   9   47  -1  1      Item 47              0
2   6   23  47  2         Item 23           0
3   4   5   23  3            Item 5         0
4   4   8   5   4               Item 8      1
5   6   29  23  3            Item 29        1
6   6   31  29  4               Item 31     1
7   9   86  47  2         Item 86           1
8   9   68  86  3            Item 68        0
9   9   67  68  4               Item 67     0

答案 1 :(得分:0)

您应该使用递归查询

此处是最左侧查询的示例,您可以通过将展示位置更改为1来轻松将其更改为最右侧的查询

with leftmost(ParentId,Id,depth) as (
    select t.Id,t.Id,0
    from #BinaryTree t
    union all
    select lm.parentid,t.Id,lm.depth+1
    from leftmost lm
        join #BinaryTree t on lm.Id = t.ParentId
    where t.Placement = 0 -- change to 1 for right most
)
select top 1 Id
from leftmost
where parentid = 47 --replace with the id you query
order by depth desc