Binary Tree Get Bottom extreme Left or Right

时光总嘲笑我的痴心妄想 提交于 2019-12-10 18:47:58

问题


I have a table that stores a binary tree as follows:

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
.
.
.

Using MSSQL now, I need to get BottomLeft of a given id, in this example, for 47 its bottom left is 5 and I need to get the bottom right of a given id, in this example for 47 its bottom right is 86

Bottom left or right is not the lowest level left or right, but extreme outside left or right leaf.

How do I write an sql that gives me a bottom left or right for a given Id?

Above placement of 0 is left and 1 is right


回答1:


You should use recursive query

here is example for leftmost query, you can easy change it to rightmost query by changing the placement to 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



回答2:


Note: The final where is commented out to illustrate the full hierarchy.

Create Demonstrative Table

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)

The 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              

Returns

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


来源:https://stackoverflow.com/questions/39251294/binary-tree-get-bottom-extreme-left-or-right

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!