Sql 二叉树得到最左或最右的底部
我有一个存储二叉树的表,如下所示:Sql 二叉树得到最左或最右的底部,sql,sql-server,binary-tree,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 . . .
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的左下角,在这个例子中,47的左下角是5
我需要得到给定id的右下角,在这个例子中,47的右下角是86
左下角或右下角不是左下角或右下角的最低层,而是左下角或右下角的最外层
如何编写为给定Id提供左下角或右下角的sql?
以上位置0为左,1为右
注意:注释掉最后一个where,以说明完整的层次结构 创建演示表
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
您应该使用递归查询 下面是最左侧查询的示例,您可以通过将位置更改为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
我很难理解为什么8不是左下角,62不是右下角。如果99存在,它会是右下角吗?如果6存在,它会是左下角吗?我在数据中看不到有左有右。。。。或者仅仅使用最小/最大值就可以在ID上工作?@xQbert要获得47的左下角,您必须只遍历您的左孩子,而不要遍历右侧的ID。对了,我现在明白了。位置0表示左1表示右。我希望我的输出为5,而不是搜索底部时的所有这些详细信息left@JustinHomes修改sql以包含“和cteCD.Placement=0”,其中输入的是Id?因为一个表可以有多个这样的二叉树,即使对于这棵树,如果我给子节点29,它应该给右下角40,左下角29itself@JustinHomes当我使用parm Declare side int=0时,设置top--Declare[at]top int=null;声明searchId INT=47;与literalit的SQL-SERVER优化相比,这似乎运行得非常慢。您可以尝试选项(重新编译)
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