计算二叉树节点的CTE

时间:2014-11-18 06:29:57

标签: sql sql-server sql-server-2008

我有这样的表结构:

Create table #table(advId int identity(1,1),name nvarchar(100),Mode nvarchar(5),ReferId int )

 insert into #table(name,Mode,ReferId)values('King','L',0)
 insert into #table(name,Mode,ReferId)values('Fisher','L',1)
 insert into #table(name,Mode,ReferId)values('Manasa','R',1)
 insert into #table(name,Mode,ReferId)values('Deekshit','L',2)
 insert into #table(name,Mode,ReferId)values('Sujai','R',2)
 insert into #table(name,Mode,ReferId)values('Fedric','L',3)
 insert into #table(name,Mode,ReferId)values('Bruce','R',3)
 insert into #table(name,Mode,ReferId)values('paul','L',4)
 insert into #table(name,Mode,ReferId)values('walker','R',4)
 insert into #table(name,Mode,ReferId)values('Diesel','L',5)
 insert into #table(name,Mode,ReferId)values('Jas','R',5)
 insert into #table(name,Mode,ReferId)values('Edward','L',6)
 insert into #table(name,Mode,ReferId)values('Lara','R',6)

 select *from #table

如何编写CTE以在级别基础上计算二进制树节点。 这是一个例子, enter image description here

现在,我想要做的是如果我要计算下线节点的数量。这意味着我想计算' 1'所以我期待的结果集

count level mode
1     1      L
1     1      R
2     2      L
2     2      R
4     3      L
2     3      R

我如何实现这一点,我尝试过这个

with cte (advId,ReferId,mode,Level)
as
(
 select advId,ReferId,mode,0 as Level from #table where advid=1
 union all
 select a.advId,a.ReferId,a.mode ,Level+1 from #table   as a inner join cte as b on b.advId=a.referId
 )
 select *From cte order by Level

2 个答案:

答案 0 :(得分:0)

您应该使用聚合SQL作为最后一个语句(Group by Lebvel,mode):

with cte (advId,mode,Level)
as
(
 select advId,mode,0 as Level from table1 where advid=1
 union all
 select a.advId,a.mode ,b.Level+1 from table1 as a 
        inner join cte as b on b.advId=a.referId
)
select count(*),Level,mode From cte 
where Level<>0
group by level,mode
order by level,mode

SQLFiddle demo

答案 1 :(得分:0)

最后我创建了存储过程

declare @advId int,@L_advId int,@R_advId int,@level int,@L_count int ,@R_count int, @startId int, @EndId int;
set @advId=1;
with cte (advId,ReferId,mode,Level)
as
(
 select advId,ReferId,mode,0 as Level from #table where advId=@advId
 union all
 select a.advId,a.ReferId,a.mode ,Level+1 from #table   as a inner join cte as b on b.advId=a.ReferId
 )
 select  distinct top 1 @EndId= Level from cte   order by Level desc;
 set @startId =0;
 while (@startId<@EndId)
 begin
with cte (advId,mode,Level)
as
(
 select advId,mode,0 as Level from #table where advid=@advId
 union all
 select a.advId,a.mode ,b.Level+1 from #table as a 
        inner join cte as b on b.advId=a.referId
)
select @L_advId=[L],@R_advId=[R],@level=[Level] from(select advId,mode,[level] from cte )up pivot (sum(advId) for mode in([L],[R]))  cte  where level=1;
 with cte (advId,mode,Level)
as
(
 select advId,mode,0 as Level from #table where advid=@L_advId
 union all
 select a.advId,a.mode ,b.Level+1 from #table as a 
        inner join cte as b on b.advId=a.referId
)
select @L_count=COUNT(*)  From cte where level=@startId ;

 with cte (advId,mode,Level)
as
(
 select advId,mode,0 as Level from #table where advid=@R_advId
 union all
 select a.advId,a.mode ,b.Level+1 from #table as a 
        inner join cte as b on b.advId=a.referId
)
select @R_count=COUNT(*)  From cte where level=@startId ;
select @L_count as LCount ,@R_count as Rcount ,@startId as level

set @startId=@startId+1;

end

我已将该数据存储到虚拟表中并解决了问题。 谢谢

相关问题