有关sql树型结构统计的问题:

时间:2021-03-12 12:59:00
现有类似的表结构,其实的score字段是通过统计出来的,实际情况中是不存在这样一个表的。
要求统计出每个节点及这个节点的所有子结点的score值。

我现在用递归函数,对每个结点做一次递归,但效率不行,因为函数要不能访问临时表,我创建了临界的基本表,每次调用此过程的时候用统计出来的信息来填充此表,如果在并发的情况下,这样效率明显不行,
请高手指教。

CREATE TABLE tbTest
(id nvarchar(5),
 parentID nvarchar(5),
 score decimal(18,2)
)

insert into tbTest
select '1','',10
union all
select '2','1',30
union all
select '3','2',30
union all
select '4','1',50
union all
select '5','',10
union all
select '6','5',30

select * from tbTest

40 个解决方案

#1


sf

#2


咋一看,原来是火鸟大侠

#3


db

#4


引用 2 楼 xupeihuagudulei 的回复:
咋一看,原来是火鸟大侠


小虾是来诚心请教各位的~~多多指教。

#5


你要什么结果 ,只要根? 还是任意节点?

#6


/*
Microsoft SQL Server 2008 (RTM) - 10.0.1600.22 (Intel X86)   Jul  9 2008 14:43:34   Copyright (c) 
1988-2008 Microsoft Corporation  Enterprise Evaluation Edition on Windows NT 5.1 <X86> 
(Build 2600: Service Pack 3) 
 愿和大家共同进步
如有雷同、实属巧合
●●●●●2009-09-03 17:47:36.077●●●●●
 ★★★★★soft_wsx★★★★★
*/
--树型结构处理之双编号(广度深度排序)
if OBJECTPROPERTY(object_id('tb'),'isusertable')<>0 
  drop table tb
create table tb(ybh nvarchar(10),ebh nvarchar(10),beizhu nvarchar(1000))
insert tb
select '0001',null,'云南省'
union all select '0002','0001','昆明市'
union all select '0003','0001','昭通市'
union all select '0009','0001','大理市'
union all select '0008',null,'四川省'
union all select '0004',null,'贵州省'
union all select '0005','0002','五华区'
union all select '0007','0002','水富县'
union all select '0006','0005','西园路192号'
union all select '0010','0006','金色梧桐'
union all select '0011','0010','科技有限公司'
union all select '0015','0007','两碗乡'
union all select '0013','0015','两碗村'
union all select '0012','0013','某跨国集团董事长'
union all select '0014','0008','成都市'

--select * from tb
--广度排序(先显示第一层节点,再显示第二次节点......)
--定义辅助表
declare @level_tb table(bh nvarchar(10),level int)
declare @level int
set @level=0
insert @level_tb(bh,level)
select ybh,@level from tb where ebh is null
while @@ROWCOUNT>0
  begin
    set @level=@level+1
    insert @level_tb(bh,level)
      select ybh,@level 
        from tb a,@level_tb b
        where a.ebh=b.bh 
              and b.level=@level-1
  end 
  select a.*,b.* from tb a,@level_tb b where a.ybh=b.bh order by level
/*
ybh ebh beizhu bh level
0001 NULL 云南省 0001 0
0008 NULL 四川省 0008 0
0004 NULL 贵州省 0004 0
0002 0001 昆明市 0002 1
0003 0001 昭通市 0003 1
0009 0001 大理市 0009 1
0014 0008 成都市 0014 1
0005 0002 五华区 0005 2
0007 0002 水富县 0007 2
0006 0005 西园路192号 0006 3
0015 0007 两碗乡 0015 3
0010 0006 金色梧桐 0010 4
0013 0015 两碗村 0013 4
0011 0010 科技有限公司 0011 5
0012 0013 某跨国集团董事长 0012 5
*/
  
  --深度排序(模拟单编码法)
   declare @level_tt table(ybh nvarchar(1000),ebh nvarchar(1000),level int)
  declare @level int
  set @level=0
  insert @level_tt(ybh,ebh,level)
  select ybh,ybh,@level from tb where ebh is null
  while @@ROWCOUNT>0
  begin 
          set @level=@level+1
          insert @level_tt(ybh,ebh,level)
          select a.ybh,b.ebh+a.ybh,@level
            from tb a,@level_tt b
            where a.ebh=b.ybh and b.level=@level-1
 end
select space(b.level*2)+'----'+a.beizhu,a.*,b.*
  from tb a,@level_tt b
  where a.ybh=b.ybh
  order by b.ebh
/*(无列名) ybh ebh beizhu ybh ebh level
----云南省 0001 NULL 云南省 0001 0001 0
  ----昆明市 0002 0001 昆明市 0002 00010002 1
    ----五华区 0005 0002 五华区 0005 000100020005 2
      ----西园路192号 0006 0005 西园路192号 0006 0001000200050006 3
        ----金色梧桐 0010 0006 金色梧桐 0010 00010002000500060010 4
          ----科技有限公司 0011 0010 科技有限公司 0011 000100020005000600100011 5
    ----水富县 0007 0002 水富县 0007 000100020007 2
      ----两碗乡 0015 0007 两碗乡 0015 0001000200070015 3
        ----两碗村 0013 0015 两碗村 0013 00010002000700150013 4
          ----某跨国集团董事长 0012 0013 某跨国集团董事长 0012 000100020007001500130012 5
  ----昭通市 0003 0001 昭通市 0003 00010003 1
  ----大理市 0009 0001 大理市 0009 00010009 1
----贵州省 0004 NULL 贵州省 0004 0004 0
----四川省 0008 NULL 四川省 0008 0008 0
  ----成都市 0014 0008 成都市 0014 00080014 1
  */
  
  
  
  --查找子节点(包括本身节点和子节点)
 declare @level_tt table(ybh nvarchar(1000),ebh nvarchar(1000),level int)
  declare @level int
  set @level=0
  insert @level_tt(ybh,ebh,level)
  select ybh,ybh,@level from tb where ybh='0005'
  while @@ROWCOUNT>0
  begin 
          set @level=@level+1
          insert @level_tt(ybh,ebh,level)
          select a.ybh,b.ebh+a.ybh,@level
            from tb a,@level_tt b
            where a.ebh=b.ybh and b.level=@level-1
 end
select space(b.level*2)+'----'+a.beizhu,a.*,b.*
  from tb a,@level_tt b
  where a.ybh=b.ybh
  order by b.ebh
  
 /*
 (无列名) ybh ebh beizhu ybh ebh level
----五华区 0005 0002 五华区 0005 0005 0
  ----西园路192号 0006 0005 西园路192号 0006 00050006 1
    ----金色梧桐 0010 0006 金色梧桐 0010 000500060010 2
      ----科技有限公司 0011 0010 科技有限公司 0011 0005000600100011 3
      */
  
  --查的父节点(包括本身节点和所有的你节点)
 declare @level_tt table(ybh nvarchar(1000),ebh nvarchar(1000),level int)
  declare @level int
  set @level=0
  insert @level_tt(ybh,ebh,level)
  select ybh,ebh,@level from tb where ebh='0005'
  while @@ROWCOUNT>0
  begin 
          set @level=@level+1
          insert @level_tt(ybh,ebh,level)
          select a.ebh,b.ebh+a.ebh,@level
            from tb a,@level_tt b
            where a.ybh=b.ybh and b.level=@level-1
 end
select space(b.level*2)+'----'+a.beizhu,a.*,b.*
  from tb a,@level_tt b
  where a.ybh=b.ybh
  order by b.ebh desc
 
 /*
 (无列名) ybh ebh beizhu ybh ebh level
      ----云南省 0001 NULL 云南省 0001 0005000500020001 3
    ----昆明市 0002 0001 昆明市 0002 000500050002 2
  ----五华区 0005 0002 五华区 0005 00050005 1
----西园路192号 0006 0005 西园路192号 0006 0005 0
*/
  



本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/soft_wsx/archive/2009/09/04/4521091.aspx
看下下

#7


2005的CTE也试了吗?

#8


引用 4 楼 yygyogfny 的回复:
引用 2 楼 xupeihuagudulei 的回复:
咋一看,原来是火鸟大侠


小虾是来诚心请教各位的~~多多指教。
指教不敢,因为我比你还菜,
等牛人帮你看吧

#9


引用 5 楼 happyflystone 的回复:
你要什么结果 ,只要根? 还是任意节点?


所有结点
不止一个根结点,
如果是叶子结点,则是结子节点的值,
如果不是叶子,就统计此节点下所有的节点。

#10


乔峰的看看

#11


帮顶 是不是能够在临时的基本表上做的文章?

#12


2005的话用CTE来递归

#13


引用 7 楼 htl258 的回复:
2005的CTE也试了吗?


我现在就是用CTE来做的递归查结点,另一个左连接表用来做统计结点的值来填充这个score.

但cte里用不了聚合函数,不得已才改用递归函数,但效率太差。。

#14


你想要的结果是什么?

#15


--> 测试数据:@tb
create  table tb([user_group_id] int,[per_group_id] int,[user_group_name] varchar(10))
insert tb
select 1,0,'总管理员' union all
select 2,1,'一级管理员' union all
select 3,2,'二级管理员' union all
select 4,3,'三级管理员' union all
select 8,4,'四级管理员' union all
select 10,8,'五级管理员'

--2000
---创建函数
CREATE FUNCTION f_Cid(@name varchar(10))
RETURNS @t TABLE(ID varchar(10),Level int)
AS
BEGIN
DECLARE @Level int,@id int
SET @Level=1
set @id=(select [per_group_id] from tb where [user_group_name]=@name )
INSERT @t SELECT @ID,@Level
WHILE @@ROWCOUNT>0
BEGIN
SET @Level=@Level+1
INSERT @t SELECT a.[user_group_id],@Level
FROM tb a,@t b
WHERE a.[per_group_id]=b.id
AND b.Level=@Level-1
END
RETURN
END
GO

--调用函数查询二级管理员及其所有子节点
SELECT a.*
FROM tb a,f_Cid('二级管理员') b
WHERE a.[per_group_id]=b.id

/*
user_group_id per_group_id user_group_name
------------- ------------ ---------------
3             2            二级管理员
4             3            三级管理员
8             4            四级管理员
10            8            五级管理员

(4 行受影响)


*/


--2005

;with t as(
select * from tb where [user_group_name]='二级管理员'
union all
select a.* from tb a  ,t where a.[per_group_id]=t.[user_group_id]

)
select * from t

/*
user_group_id per_group_id user_group_name
------------- ------------ ---------------
3             2            二级管理员
4             3            三级管理员
8             4            四级管理员
10            8            五级管理员

(4 行受影响)
*/

是这样的吗?不明白

#16


--查找子节点(包括本身节点和子节点)
 declare @level_tt table(ybh nvarchar(1000),ebh nvarchar(1000),level int)
  declare @level int
  set @level=0
  insert @level_tt(ybh,ebh,level)
  select ybh,ybh,@level from tb where ybh='0005'  --要查找的节点
  while @@ROWCOUNT>0
  begin 
          set @level=@level+1
          insert @level_tt(ybh,ebh,level)
          select a.ybh,b.ebh+a.ybh,@level
            from tb a,@level_tt b
            where a.ebh=b.ybh and b.level=@level-1
 end
select space(b.level*2)+'----'+a.beizhu,a.*,b.*
  from tb a,@level_tt b
  where a.ybh=b.ybh
  order by b.ebh

#17


引用 12 楼 fredrickhu 的回复:
2005的话用CTE来递归


这个情况比较复杂,涉及到这多棵树型结构的查询,我里面有用到CTE

#18


只能给你看一些经典例子了
--测试数据   深度排序     
  DECLARE   @t   TABLE(ID   char(3),PID   char(3),Name   nvarchar(10))   
  INSERT   @t   SELECT   '001',NULL   ,'山东省'   
  UNION   ALL   SELECT   '002','001','烟台市'   
  UNION   ALL   SELECT   '004','002','招远市'   
  UNION   ALL   SELECT   '003','001','青岛市'   
  UNION   ALL   SELECT   '005',NULL   ,'四会市'   
  UNION   ALL   SELECT   '006','005','清远市'   
  UNION   ALL   SELECT   '007','006','小分市'   
    
  --深度排序显示处理   
  --生成每个节点的编码累计(相同当单编号法的编码)   
  DECLARE   @t_Level   TABLE(ID   char(3),Level   int,Sort   varchar(8000))   
  DECLARE   @Level   int   
  SET   @Level=0   
  INSERT   @t_Level   SELECT   ID,@Level,ID   
  FROM   @t   
  WHERE   PID   IS   NULL   
  WHILE   @@ROWCOUNT>0   
  BEGIN   
  SET   @Level=@Level+1   
  INSERT   @t_Level   SELECT   a.ID,@Level,b.Sort+a.ID   
  FROM   @t   a,@t_Level   b   
  WHERE   a.PID=b.ID   
  AND   b.Level=@Level-1   
  END   
    
  --显示结果   
  SELECT   a.*   
  FROM   @t   a,@t_Level   b   
  WHERE   a.ID=b.ID   
  ORDER   BY   b.Sort   
  /*--结果   
  ID       PID       Name                 
  ------   ---------   ----------     
  001     NULL   山东省   
  002     001       烟台市   
  004     002       招远市   
  003     001       青岛市   
  005     NULL   四会市   
  006     005       清远市   
  007     006       小分市   
  --*/

--查询指定节点及其所有子节点的函数   
  CREATE   FUNCTION   f_Cid(@ID   char(3))   
  RETURNS   @t_Level   TABLE(ID   char(3),Level   int)   
  AS   
  BEGIN   
  DECLARE   @Level   int   
  SET   @Level=1   
  INSERT   @t_Level   SELECT   @ID,@Level   
  WHILE   @@ROWCOUNT>0   
  BEGIN   
  SET   @Level=@Level+1   
  INSERT   @t_Level   SELECT   a.ID,@Level   
  FROM   tb   a,@t_Level   b   
  WHERE   a.PID=b.ID   
  AND   b.Level=@Level-1   
  END   
  RETURN   
  END   
  GO   
    
  --调用函数查询002及其所有子节点   
  SELECT   a.*   
  FROM   tb   a,f_Cid('002')   b   
  WHERE   a.ID=b.ID   
  /*--结果   
  ID       PID     Name                 
  ------   -------   ----------     
  002     001     烟台市   
  004     002     招远市   
  --*/

 

--测试数据
DECLARE @t TABLE(ID char(3),PID char(3),Name nvarchar(10))
INSERT @t SELECT '001',NULL ,'山东省'
UNION ALL SELECT '002','001','烟台市'
UNION ALL SELECT '004','002','招远市'
UNION ALL SELECT '003','001','青岛市'
UNION ALL SELECT '005',NULL ,'四会市'
UNION ALL SELECT '006','005','清远市'
UNION ALL SELECT '007','006','小分市'

--深度排序显示处理
--生成每个节点的编码累计(相同当单编号法的编码)
DECLARE @t_Level TABLE(ID char(3),Level int,Sort varchar(8000))
DECLARE @Level int
SET @Level=0
INSERT @t_Level SELECT ID,@Level,ID
FROM @t
WHERE PID IS NULL
WHILE @@ROWCOUNT>0
BEGIN
    SET @Level=@Level+1
    INSERT @t_Level SELECT a.ID,@Level,b.Sort+a.ID
    FROM @t a,@t_Level b
    WHERE a.PID=b.ID
        AND b.Level=@Level-1
END

--显示结果
SELECT SPACE(b.Level*2)+'|--'+a.Name
FROM @t a,@t_Level b
WHERE a.ID=b.ID
ORDER BY b.Sort
/*--结果
|--山东省
  |--烟台市
    |--招远市
  |--青岛市
|--四会市
  |--清远市
    |--小分市
--*/


--树型结构处理之双编号(广度深度排序)
if OBJECTPROPERTY(object_id('tb'),'isusertable')<>0 
  drop table tb
create table tb(ybh nvarchar(10),ebh nvarchar(10),beizhu nvarchar(1000))
insert tb
select '0001',null,'云南省'
union all select '0002','0001','昆明市'
union all select '0003','0001','昭通市'
union all select '0009','0001','大理市'
union all select '0008',null,'四川省'
union all select '0004',null,'贵州省'
union all select '0005','0002','五华区'
union all select '0007','0002','水富县'
union all select '0006','0005','西园路192号'
union all select '0010','0006','金色梧桐3-702'
union all select '0011','0010','昆明越科时空科技有限公司'
union all select '0015','0007','两碗乡'
union all select '0013','0015','两碗村'
union all select '0012','0013','某跨国集团董事长'
union all select '0014','0008','成都市'

  
  --深度排序(模拟单编码法)
   declare @level_tt table(ybh nvarchar(1000),ebh nvarchar(1000),level int)
  declare @level int
  set @level=0
  insert @level_tt(ybh,ebh,level)
  select ybh,ybh,@level from tb where ebh is null
  while @@ROWCOUNT>0
  begin 
          set @level=@level+1
          insert @level_tt(ybh,ebh,level)
          select a.ybh,b.ebh+a.ybh,@level
            from tb a,@level_tt b
            where a.ebh=b.ybh and b.level=@level-1
 end
select space(b.level*2)+'----'+a.beizhu,a.*,b.*
  from tb a,@level_tt b
  where a.ybh=b.ybh
  order by b.ebh
/*
(结果)    ybh    ebh    beizhu    ybh    ebh    level
----云南省    0001    NULL    云南省    0001    0001    0
  ----昆明市    0002    0001    昆明市    0002    00010002    1
    ----五华区    0005    0002    五华区    0005    000100020005    2
      ----西园路192号    0006    0005    西园路192号    0006    0001000200050006    3
        ----金色梧桐3-702    0010    0006    金色梧桐3-702    0010    00010002000500060010    4
          ----昆明越科时空科技有限公司    0011    0010    昆明越科时空科技有限公司    0011    000100020005000600100011    5
    ----水富县    0007    0002    水富县    0007    000100020007    2
      ----两碗乡    0015    0007    两碗乡    0015    0001000200070015    3
        ----两碗村    0013    0015    两碗村    0013    00010002000700150013    4
          ----某跨国集团董事长    0012    0013    某跨国集团董事长    0012    000100020007001500130012    5
  ----昭通市    0003    0001    昭通市    0003    00010003    1
  ----大理市    0009    0001    大理市    0009    00010009    1
----贵州省    0004    NULL    贵州省    0004    0004    0
----四川省    0008    NULL    四川省    0008    0008    0
  ----成都市    0014    0008    成都市    0014    00080014    1
  */
  
  --查找子节点(包括本身节点和子节点)
 declare @level_tt table(ybh nvarchar(1000),ebh nvarchar(1000),level int)
  declare @level int
  set @level=0
  insert @level_tt(ybh,ebh,level)
  select ybh,ybh,@level from tb where ybh='0005'
  while @@ROWCOUNT>0
  begin 
          set @level=@level+1
          insert @level_tt(ybh,ebh,level)
          select a.ybh,b.ebh+a.ybh,@level
            from tb a,@level_tt b
            where a.ebh=b.ybh and b.level=@level-1
 end
select space(b.level*2)+'----'+a.beizhu,a.*,b.*
  from tb a,@level_tt b
  where a.ybh=b.ybh
  order by b.ebh
/*
(无列名)    ybh    ebh    beizhu    ybh    ebh    level
----五华区    0005    0002    五华区    0005    0005    0
  ----西园路192号    0006    0005    西园路192号    0006    00050006    1
    ----金色梧桐3-702    0010    0006    金色梧桐3-702    0010    000500060010    2
      ----昆明越科时空科技有限公司    0011    0010    昆明越科时空科技有限公司    0011    0005000600100011    3
*/
  


/*
标题:查询各节点的父路径函数
作者:爱新觉罗·毓华(十八年风雨,守得冰山雪莲花开)  
时间:2008-05-12
地点:广东深圳
*/

/*
原始数据及要求结果如下:
--食品 
  --水果 
    --香蕉 
    --苹果    
  --蔬菜 
    --青菜
id          pid         name                 
----------- ----------- -------------------- 
1           0           食品
2           1           水果
3           1           蔬菜
4           2           香蕉
5           2           苹果
6           3           青菜

要求得到各节点的父路径即如下结果:
id  pid name  路径                         
--- --- ----- ---------------
1   0   食品  食品
2   1   水果  食品,水果
3   1   蔬菜  食品,蔬菜
4   2   香蕉  食品,水果,香蕉
5   2   苹果  食品,水果,苹果
6   3   青菜  食品,蔬菜,青菜 
*/

create table tb (id int , pid int , name nvarchar(20)) 
insert into tb values(1 , 0 , '食品')
insert into tb values(2 , 1 , '水果')
insert into tb values(3 , 1 , '蔬菜')
insert into tb values(4 , 2 , '香蕉')
insert into tb values(5 , 2 , '苹果')
insert into tb values(6 , 3 , '青菜')
go

--查询各节点的父路径函数
create function f_pid(@id int) returns varchar(100)
as
begin
  declare @re_str as varchar(100)
  set @re_str = ''
  select @re_str = name from tb where id = @id
  while exists (select 1 from tb where id = @id and pid <> 0)
    begin
      select @id = b.id , @re_str = b.name + ',' + @re_str from tb a , tb b where a.id = @id and a.pid = b.id
    end
  return @re_str
end
go

select * , dbo.f_pid(id) 路径 from tb order by id

drop table tb
drop function f_pid

#19


id parentid,score
1,'',130(10+30+30+50),
2,'1',60(30+30)
3,'2',30
4,'1',50
5,'',40(10+30)
6,'5',30


我要的结果是这样。

#20


小F兄。。

深度排序我有了解过,,
但今天的情况不一样咯。

#21


呵呵 我不是很会 SORRY

#22


引用 21 楼 fredrickhu 的回复:
呵呵 我不是很会 SORRY


别这样咯~~

#23


引用 5 楼 happyflystone 的回复:
你要什么结果 ,只要根? 还是任意节点?


id parentid,score 
1,'',130(10+30+30+50), 
2,'1',60(30+30) 
3,'2',30 
4,'1',50 
5,'',40(10+30) 
6,'5',30 

我要的结果是这样。

#24


引用 19 楼 yygyogfny 的回复:
id parentid,score
1,'',130(10+30+30+50),
2,'1',60(30+30)
3,'2',30
4,'1',50
5,'',40(10+30)
6,'5',30

我要的结果是这样。


这个找石头哥帮你搞定。

#25


;with liang as
(
    select *,total = score from tbTest as a
    where not exists(select * from tbTest where a.id = parentid)
    union all
    select a.*,cast(b.total + a.score as decimal(18,2))
    from tbTest as a
       join liang as b
    on a.id = b.parentid
)
select a.id,a.parentid,isnull(b.score,a.score) as score
from tbTest as a
   left join (select id,parentid,sum(total) as score 
              from liang group by id,parentid) as b
on a.id=b.id and a.parentid=b.parentid

#26


引用 25 楼 liangck 的回复:
SQL code;with liangas
(select*,total= scorefrom tbTestas awherenotexists(select*from tbTestwhere a.id= parentid)unionallselect a.*,cast(b.total+ a.scoreasdecimal(18,2))from tbTestas ajoin liangas bon ¡­



小梁P,果然厉害,,把统计移到外层,,我咋没有想到呢。。 有关sql树型结构统计的问题:

#27


引用 26 楼 yygyogfny 的回复:
引用 25 楼 liangck 的回复:
SQL code;with liangas
(select*,total= scorefrom tbTestas awherenotexists(select*from tbTestwhere a.id= parentid)unionallselect a.*,cast(b.total+ a.scoreasdecimal(18,2))from tbTestas ajoin liangas bon ¡­



小梁P,果然厉害,,把统计移到外层,,我咋没有想到呢。。
有关sql树型结构统计的问题:

#29


引用 25 楼 liangck 的回复:
SQL code;with liangas
(select*,total= scorefrom tbTestas awherenotexists(select*from tbTestwhere a.id= parentid)unionallselect a.*,cast(b.total+ a.scoreasdecimal(18,2))from tbTestas ajoin liangas bon ¡­

的确不错.

#30



双编号逐级汇总
if OBJECTPROPERTY(object_id('tb'),'isusertable')<>0 
  drop table tb
  go
create table tb(ybh nvarchar(10),ebh nvarchar(10),beizhu nvarchar(1000),num decimal(14,2))
go
insert tb
select '0001',null,'云南省',100
union all select '0002','0001','昆明市',200
union all select '0003','0001','昭通市',300.3
union all select '0009','0001','大理市',400.4
union all select '0008',null,'四川省',500.5
union all select '0004',null,'贵州省',600.6
union all select '0005','0002','五华区',101.1
union all select '0007','0003','水富县',102.1
union all select '0006','0005','西园路192号',202.1
union all select '0010','0006','金色梧桐3-702',202.2
union all select '0011','0010','昆空科技有限公司',303.1
union all select '0015','0007','两碗乡',303.2
union all select '0013','0015','两碗村',303.4
union all select '0012','0013','某跨国集团董事',444.1
union all select '0014','0008','成都市',111.10






declare @level_tt table(ybh nvarchar(1000),ebh nvarchar(1000),level int)
  declare @level int
  set @level=0
  insert @level_tt(ybh,ebh,level)
  select ybh,ybh,@level from tb where ebh is null
  while @@ROWCOUNT>0
  begin 
          set @level=@level+1
          insert @level_tt(ybh,ebh,level)
          select a.ybh,b.ebh+a.ybh,@level
            from tb a,@level_tt b
            where a.ebh=b.ybh and b.level=@level-1
 end
select a.ybh,a.ebh,a.beizhu,a.num,SUM(a.num) as 汇总
  from tb a,@level_tt b,tb c,@level_tt d
  where a.ybh=b.ybh and c.ybh=d.ybh
        and d.ebh like b.ebh+'%'
  group by a.ybh,a.ebh,a.beizhu,a.num
  order by a.ebh
  
  /*
  ybh ebh beizhu num 汇总
0001 NULL 云南省 100.00 1200.00
0004 NULL 贵州省 600.60 600.60
0008 NULL 四川省 500.50 1001.00
0002 0001 昆明市 200.00 1000.00
0003 0001 昭通市 300.30 1501.50
0009 0001 大理市 400.40 400.40
0005 0002 五华区 101.10 404.40
0007 0003 水富县 102.10 408.40
0006 0005 西园路192号 202.10 606.30
0010 0006 金色梧桐3-702 202.20 404.40
0015 0007 两碗乡 303.20 909.60
0014 0008 成都市 111.10 111.10
0011 0010 昆空科技有限公司 303.10 303.10
0012 0013 某跨国集团董事 444.10 444.10
0013 0015 两碗村 303.40 606.80
*/
这样行吗?

#31


CREATE TABLE tbTest --drop table tbtest
(id nvarchar(5), 
parentID nvarchar(5), 
score decimal(18,2) 


insert into tbTest 
select '01','',10 
union all 
select '02','01',30 
union all 
select '03','02',30 
union all 
select '04','01',50 
union all 
select '05','',10 
union all 
select '06','05',30 



declare @level_tt table(id nvarchar(1000),parentID nvarchar(1000),level int)
  declare @level int
  set @level=0
  insert @level_tt(id,parentID,level)
  select id,id,@level from tbTest where isnull(parentID,'')=''  
  while @@ROWCOUNT>0
  begin 
          set @level=@level+1
          insert @level_tt(id,parentID,level)
          select a.id,cast(b.parentID as varchar)+cast(a.id as varchar),@level
            from tbTest a,@level_tt b
            where a.parentID=b.id and b.level=@level-1
 end
 select * from @level_tt
select a.id,a.parentID,a.score,SUM(c.score) as 汇总
  from tbTest a,@level_tt b,tbTest c,@level_tt d
  where a.ID=b.ID and c.ID=d.ID
        and d.parentID like b.parentID+'%'
  group by a.ID,a.parentID,a.score
  order by a.parentID
  
 /*
 id parentID score 汇总
01 10.00 120.00
05 10.00 40.00
02 01 30.00 60.00
04 01 50.00 50.00
03 02 30.00 30.00
06 05 30.00 30.00
*/
这样就对了

#32


厉害,学习.

#33


再定义一个中间表。记录父子关系,每次统计的时候从中间表中查询所有子节点记录,然后再统计。希望这个思路可以帮到你。

例如:
CREATE TABLE tbTestPath 
(id nvarchar(5), 
parentID nvarchar(5)

-------------------------------------------
构建如下数据:
id      parentid
1 1
2 1
3 1
3 2
4 1
5 5
6 5
2 2
3 3
4 4
6 6


select sum(score),parentid from (select tbTest.score ,tbTestPath.*from tbTest inner join tbTestPath on tbTest.id=tbTestPath.id) as a group by a.parentID

#34


学习

#35


进来学习

#36


参看:
使用SQL Server 2008中的hierarchyid类型来设计具有树型层次关系的表
http://blog.csdn.net/tjvictor/archive/2009/07/30/4395681.aspx

SQL Server中如何存储具有层次关系的表
http://blog.csdn.net/tjvictor/archive/2009/07/30/4395677.aspx

#37


引用 23 楼 yygyogfny 的回复:
引用 5 楼 happyflystone 的回复:
 你要什么结果 ,只要根? 还是任意节点?


 id parentid,score
 1,'',130(10+30+30+50),
 2,'1',60(30+30)
 3,'2',30
 4,'1',50
 5,'',40(10+30)
 6,'5',30

 我要的结果是这样。


10+30+30+50 结果不是120吗?130怎么出来的,我纠结了好久。

#38


同意楼上,我也想知道130是怎么算出来的?希望赐教!

#39


好...........

#40


好............

#1


sf

#2


咋一看,原来是火鸟大侠

#3


db

#4


引用 2 楼 xupeihuagudulei 的回复:
咋一看,原来是火鸟大侠


小虾是来诚心请教各位的~~多多指教。

#5


你要什么结果 ,只要根? 还是任意节点?

#6


/*
Microsoft SQL Server 2008 (RTM) - 10.0.1600.22 (Intel X86)   Jul  9 2008 14:43:34   Copyright (c) 
1988-2008 Microsoft Corporation  Enterprise Evaluation Edition on Windows NT 5.1 <X86> 
(Build 2600: Service Pack 3) 
 愿和大家共同进步
如有雷同、实属巧合
●●●●●2009-09-03 17:47:36.077●●●●●
 ★★★★★soft_wsx★★★★★
*/
--树型结构处理之双编号(广度深度排序)
if OBJECTPROPERTY(object_id('tb'),'isusertable')<>0 
  drop table tb
create table tb(ybh nvarchar(10),ebh nvarchar(10),beizhu nvarchar(1000))
insert tb
select '0001',null,'云南省'
union all select '0002','0001','昆明市'
union all select '0003','0001','昭通市'
union all select '0009','0001','大理市'
union all select '0008',null,'四川省'
union all select '0004',null,'贵州省'
union all select '0005','0002','五华区'
union all select '0007','0002','水富县'
union all select '0006','0005','西园路192号'
union all select '0010','0006','金色梧桐'
union all select '0011','0010','科技有限公司'
union all select '0015','0007','两碗乡'
union all select '0013','0015','两碗村'
union all select '0012','0013','某跨国集团董事长'
union all select '0014','0008','成都市'

--select * from tb
--广度排序(先显示第一层节点,再显示第二次节点......)
--定义辅助表
declare @level_tb table(bh nvarchar(10),level int)
declare @level int
set @level=0
insert @level_tb(bh,level)
select ybh,@level from tb where ebh is null
while @@ROWCOUNT>0
  begin
    set @level=@level+1
    insert @level_tb(bh,level)
      select ybh,@level 
        from tb a,@level_tb b
        where a.ebh=b.bh 
              and b.level=@level-1
  end 
  select a.*,b.* from tb a,@level_tb b where a.ybh=b.bh order by level
/*
ybh ebh beizhu bh level
0001 NULL 云南省 0001 0
0008 NULL 四川省 0008 0
0004 NULL 贵州省 0004 0
0002 0001 昆明市 0002 1
0003 0001 昭通市 0003 1
0009 0001 大理市 0009 1
0014 0008 成都市 0014 1
0005 0002 五华区 0005 2
0007 0002 水富县 0007 2
0006 0005 西园路192号 0006 3
0015 0007 两碗乡 0015 3
0010 0006 金色梧桐 0010 4
0013 0015 两碗村 0013 4
0011 0010 科技有限公司 0011 5
0012 0013 某跨国集团董事长 0012 5
*/
  
  --深度排序(模拟单编码法)
   declare @level_tt table(ybh nvarchar(1000),ebh nvarchar(1000),level int)
  declare @level int
  set @level=0
  insert @level_tt(ybh,ebh,level)
  select ybh,ybh,@level from tb where ebh is null
  while @@ROWCOUNT>0
  begin 
          set @level=@level+1
          insert @level_tt(ybh,ebh,level)
          select a.ybh,b.ebh+a.ybh,@level
            from tb a,@level_tt b
            where a.ebh=b.ybh and b.level=@level-1
 end
select space(b.level*2)+'----'+a.beizhu,a.*,b.*
  from tb a,@level_tt b
  where a.ybh=b.ybh
  order by b.ebh
/*(无列名) ybh ebh beizhu ybh ebh level
----云南省 0001 NULL 云南省 0001 0001 0
  ----昆明市 0002 0001 昆明市 0002 00010002 1
    ----五华区 0005 0002 五华区 0005 000100020005 2
      ----西园路192号 0006 0005 西园路192号 0006 0001000200050006 3
        ----金色梧桐 0010 0006 金色梧桐 0010 00010002000500060010 4
          ----科技有限公司 0011 0010 科技有限公司 0011 000100020005000600100011 5
    ----水富县 0007 0002 水富县 0007 000100020007 2
      ----两碗乡 0015 0007 两碗乡 0015 0001000200070015 3
        ----两碗村 0013 0015 两碗村 0013 00010002000700150013 4
          ----某跨国集团董事长 0012 0013 某跨国集团董事长 0012 000100020007001500130012 5
  ----昭通市 0003 0001 昭通市 0003 00010003 1
  ----大理市 0009 0001 大理市 0009 00010009 1
----贵州省 0004 NULL 贵州省 0004 0004 0
----四川省 0008 NULL 四川省 0008 0008 0
  ----成都市 0014 0008 成都市 0014 00080014 1
  */
  
  
  
  --查找子节点(包括本身节点和子节点)
 declare @level_tt table(ybh nvarchar(1000),ebh nvarchar(1000),level int)
  declare @level int
  set @level=0
  insert @level_tt(ybh,ebh,level)
  select ybh,ybh,@level from tb where ybh='0005'
  while @@ROWCOUNT>0
  begin 
          set @level=@level+1
          insert @level_tt(ybh,ebh,level)
          select a.ybh,b.ebh+a.ybh,@level
            from tb a,@level_tt b
            where a.ebh=b.ybh and b.level=@level-1
 end
select space(b.level*2)+'----'+a.beizhu,a.*,b.*
  from tb a,@level_tt b
  where a.ybh=b.ybh
  order by b.ebh
  
 /*
 (无列名) ybh ebh beizhu ybh ebh level
----五华区 0005 0002 五华区 0005 0005 0
  ----西园路192号 0006 0005 西园路192号 0006 00050006 1
    ----金色梧桐 0010 0006 金色梧桐 0010 000500060010 2
      ----科技有限公司 0011 0010 科技有限公司 0011 0005000600100011 3
      */
  
  --查的父节点(包括本身节点和所有的你节点)
 declare @level_tt table(ybh nvarchar(1000),ebh nvarchar(1000),level int)
  declare @level int
  set @level=0
  insert @level_tt(ybh,ebh,level)
  select ybh,ebh,@level from tb where ebh='0005'
  while @@ROWCOUNT>0
  begin 
          set @level=@level+1
          insert @level_tt(ybh,ebh,level)
          select a.ebh,b.ebh+a.ebh,@level
            from tb a,@level_tt b
            where a.ybh=b.ybh and b.level=@level-1
 end
select space(b.level*2)+'----'+a.beizhu,a.*,b.*
  from tb a,@level_tt b
  where a.ybh=b.ybh
  order by b.ebh desc
 
 /*
 (无列名) ybh ebh beizhu ybh ebh level
      ----云南省 0001 NULL 云南省 0001 0005000500020001 3
    ----昆明市 0002 0001 昆明市 0002 000500050002 2
  ----五华区 0005 0002 五华区 0005 00050005 1
----西园路192号 0006 0005 西园路192号 0006 0005 0
*/
  



本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/soft_wsx/archive/2009/09/04/4521091.aspx
看下下

#7


2005的CTE也试了吗?

#8


引用 4 楼 yygyogfny 的回复:
引用 2 楼 xupeihuagudulei 的回复:
咋一看,原来是火鸟大侠


小虾是来诚心请教各位的~~多多指教。
指教不敢,因为我比你还菜,
等牛人帮你看吧

#9


引用 5 楼 happyflystone 的回复:
你要什么结果 ,只要根? 还是任意节点?


所有结点
不止一个根结点,
如果是叶子结点,则是结子节点的值,
如果不是叶子,就统计此节点下所有的节点。

#10


乔峰的看看

#11


帮顶 是不是能够在临时的基本表上做的文章?

#12


2005的话用CTE来递归

#13


引用 7 楼 htl258 的回复:
2005的CTE也试了吗?


我现在就是用CTE来做的递归查结点,另一个左连接表用来做统计结点的值来填充这个score.

但cte里用不了聚合函数,不得已才改用递归函数,但效率太差。。

#14


你想要的结果是什么?

#15


--> 测试数据:@tb
create  table tb([user_group_id] int,[per_group_id] int,[user_group_name] varchar(10))
insert tb
select 1,0,'总管理员' union all
select 2,1,'一级管理员' union all
select 3,2,'二级管理员' union all
select 4,3,'三级管理员' union all
select 8,4,'四级管理员' union all
select 10,8,'五级管理员'

--2000
---创建函数
CREATE FUNCTION f_Cid(@name varchar(10))
RETURNS @t TABLE(ID varchar(10),Level int)
AS
BEGIN
DECLARE @Level int,@id int
SET @Level=1
set @id=(select [per_group_id] from tb where [user_group_name]=@name )
INSERT @t SELECT @ID,@Level
WHILE @@ROWCOUNT>0
BEGIN
SET @Level=@Level+1
INSERT @t SELECT a.[user_group_id],@Level
FROM tb a,@t b
WHERE a.[per_group_id]=b.id
AND b.Level=@Level-1
END
RETURN
END
GO

--调用函数查询二级管理员及其所有子节点
SELECT a.*
FROM tb a,f_Cid('二级管理员') b
WHERE a.[per_group_id]=b.id

/*
user_group_id per_group_id user_group_name
------------- ------------ ---------------
3             2            二级管理员
4             3            三级管理员
8             4            四级管理员
10            8            五级管理员

(4 行受影响)


*/


--2005

;with t as(
select * from tb where [user_group_name]='二级管理员'
union all
select a.* from tb a  ,t where a.[per_group_id]=t.[user_group_id]

)
select * from t

/*
user_group_id per_group_id user_group_name
------------- ------------ ---------------
3             2            二级管理员
4             3            三级管理员
8             4            四级管理员
10            8            五级管理员

(4 行受影响)
*/

是这样的吗?不明白

#16


--查找子节点(包括本身节点和子节点)
 declare @level_tt table(ybh nvarchar(1000),ebh nvarchar(1000),level int)
  declare @level int
  set @level=0
  insert @level_tt(ybh,ebh,level)
  select ybh,ybh,@level from tb where ybh='0005'  --要查找的节点
  while @@ROWCOUNT>0
  begin 
          set @level=@level+1
          insert @level_tt(ybh,ebh,level)
          select a.ybh,b.ebh+a.ybh,@level
            from tb a,@level_tt b
            where a.ebh=b.ybh and b.level=@level-1
 end
select space(b.level*2)+'----'+a.beizhu,a.*,b.*
  from tb a,@level_tt b
  where a.ybh=b.ybh
  order by b.ebh

#17


引用 12 楼 fredrickhu 的回复:
2005的话用CTE来递归


这个情况比较复杂,涉及到这多棵树型结构的查询,我里面有用到CTE

#18


只能给你看一些经典例子了
--测试数据   深度排序     
  DECLARE   @t   TABLE(ID   char(3),PID   char(3),Name   nvarchar(10))   
  INSERT   @t   SELECT   '001',NULL   ,'山东省'   
  UNION   ALL   SELECT   '002','001','烟台市'   
  UNION   ALL   SELECT   '004','002','招远市'   
  UNION   ALL   SELECT   '003','001','青岛市'   
  UNION   ALL   SELECT   '005',NULL   ,'四会市'   
  UNION   ALL   SELECT   '006','005','清远市'   
  UNION   ALL   SELECT   '007','006','小分市'   
    
  --深度排序显示处理   
  --生成每个节点的编码累计(相同当单编号法的编码)   
  DECLARE   @t_Level   TABLE(ID   char(3),Level   int,Sort   varchar(8000))   
  DECLARE   @Level   int   
  SET   @Level=0   
  INSERT   @t_Level   SELECT   ID,@Level,ID   
  FROM   @t   
  WHERE   PID   IS   NULL   
  WHILE   @@ROWCOUNT>0   
  BEGIN   
  SET   @Level=@Level+1   
  INSERT   @t_Level   SELECT   a.ID,@Level,b.Sort+a.ID   
  FROM   @t   a,@t_Level   b   
  WHERE   a.PID=b.ID   
  AND   b.Level=@Level-1   
  END   
    
  --显示结果   
  SELECT   a.*   
  FROM   @t   a,@t_Level   b   
  WHERE   a.ID=b.ID   
  ORDER   BY   b.Sort   
  /*--结果   
  ID       PID       Name                 
  ------   ---------   ----------     
  001     NULL   山东省   
  002     001       烟台市   
  004     002       招远市   
  003     001       青岛市   
  005     NULL   四会市   
  006     005       清远市   
  007     006       小分市   
  --*/

--查询指定节点及其所有子节点的函数   
  CREATE   FUNCTION   f_Cid(@ID   char(3))   
  RETURNS   @t_Level   TABLE(ID   char(3),Level   int)   
  AS   
  BEGIN   
  DECLARE   @Level   int   
  SET   @Level=1   
  INSERT   @t_Level   SELECT   @ID,@Level   
  WHILE   @@ROWCOUNT>0   
  BEGIN   
  SET   @Level=@Level+1   
  INSERT   @t_Level   SELECT   a.ID,@Level   
  FROM   tb   a,@t_Level   b   
  WHERE   a.PID=b.ID   
  AND   b.Level=@Level-1   
  END   
  RETURN   
  END   
  GO   
    
  --调用函数查询002及其所有子节点   
  SELECT   a.*   
  FROM   tb   a,f_Cid('002')   b   
  WHERE   a.ID=b.ID   
  /*--结果   
  ID       PID     Name                 
  ------   -------   ----------     
  002     001     烟台市   
  004     002     招远市   
  --*/

 

--测试数据
DECLARE @t TABLE(ID char(3),PID char(3),Name nvarchar(10))
INSERT @t SELECT '001',NULL ,'山东省'
UNION ALL SELECT '002','001','烟台市'
UNION ALL SELECT '004','002','招远市'
UNION ALL SELECT '003','001','青岛市'
UNION ALL SELECT '005',NULL ,'四会市'
UNION ALL SELECT '006','005','清远市'
UNION ALL SELECT '007','006','小分市'

--深度排序显示处理
--生成每个节点的编码累计(相同当单编号法的编码)
DECLARE @t_Level TABLE(ID char(3),Level int,Sort varchar(8000))
DECLARE @Level int
SET @Level=0
INSERT @t_Level SELECT ID,@Level,ID
FROM @t
WHERE PID IS NULL
WHILE @@ROWCOUNT>0
BEGIN
    SET @Level=@Level+1
    INSERT @t_Level SELECT a.ID,@Level,b.Sort+a.ID
    FROM @t a,@t_Level b
    WHERE a.PID=b.ID
        AND b.Level=@Level-1
END

--显示结果
SELECT SPACE(b.Level*2)+'|--'+a.Name
FROM @t a,@t_Level b
WHERE a.ID=b.ID
ORDER BY b.Sort
/*--结果
|--山东省
  |--烟台市
    |--招远市
  |--青岛市
|--四会市
  |--清远市
    |--小分市
--*/


--树型结构处理之双编号(广度深度排序)
if OBJECTPROPERTY(object_id('tb'),'isusertable')<>0 
  drop table tb
create table tb(ybh nvarchar(10),ebh nvarchar(10),beizhu nvarchar(1000))
insert tb
select '0001',null,'云南省'
union all select '0002','0001','昆明市'
union all select '0003','0001','昭通市'
union all select '0009','0001','大理市'
union all select '0008',null,'四川省'
union all select '0004',null,'贵州省'
union all select '0005','0002','五华区'
union all select '0007','0002','水富县'
union all select '0006','0005','西园路192号'
union all select '0010','0006','金色梧桐3-702'
union all select '0011','0010','昆明越科时空科技有限公司'
union all select '0015','0007','两碗乡'
union all select '0013','0015','两碗村'
union all select '0012','0013','某跨国集团董事长'
union all select '0014','0008','成都市'

  
  --深度排序(模拟单编码法)
   declare @level_tt table(ybh nvarchar(1000),ebh nvarchar(1000),level int)
  declare @level int
  set @level=0
  insert @level_tt(ybh,ebh,level)
  select ybh,ybh,@level from tb where ebh is null
  while @@ROWCOUNT>0
  begin 
          set @level=@level+1
          insert @level_tt(ybh,ebh,level)
          select a.ybh,b.ebh+a.ybh,@level
            from tb a,@level_tt b
            where a.ebh=b.ybh and b.level=@level-1
 end
select space(b.level*2)+'----'+a.beizhu,a.*,b.*
  from tb a,@level_tt b
  where a.ybh=b.ybh
  order by b.ebh
/*
(结果)    ybh    ebh    beizhu    ybh    ebh    level
----云南省    0001    NULL    云南省    0001    0001    0
  ----昆明市    0002    0001    昆明市    0002    00010002    1
    ----五华区    0005    0002    五华区    0005    000100020005    2
      ----西园路192号    0006    0005    西园路192号    0006    0001000200050006    3
        ----金色梧桐3-702    0010    0006    金色梧桐3-702    0010    00010002000500060010    4
          ----昆明越科时空科技有限公司    0011    0010    昆明越科时空科技有限公司    0011    000100020005000600100011    5
    ----水富县    0007    0002    水富县    0007    000100020007    2
      ----两碗乡    0015    0007    两碗乡    0015    0001000200070015    3
        ----两碗村    0013    0015    两碗村    0013    00010002000700150013    4
          ----某跨国集团董事长    0012    0013    某跨国集团董事长    0012    000100020007001500130012    5
  ----昭通市    0003    0001    昭通市    0003    00010003    1
  ----大理市    0009    0001    大理市    0009    00010009    1
----贵州省    0004    NULL    贵州省    0004    0004    0
----四川省    0008    NULL    四川省    0008    0008    0
  ----成都市    0014    0008    成都市    0014    00080014    1
  */
  
  --查找子节点(包括本身节点和子节点)
 declare @level_tt table(ybh nvarchar(1000),ebh nvarchar(1000),level int)
  declare @level int
  set @level=0
  insert @level_tt(ybh,ebh,level)
  select ybh,ybh,@level from tb where ybh='0005'
  while @@ROWCOUNT>0
  begin 
          set @level=@level+1
          insert @level_tt(ybh,ebh,level)
          select a.ybh,b.ebh+a.ybh,@level
            from tb a,@level_tt b
            where a.ebh=b.ybh and b.level=@level-1
 end
select space(b.level*2)+'----'+a.beizhu,a.*,b.*
  from tb a,@level_tt b
  where a.ybh=b.ybh
  order by b.ebh
/*
(无列名)    ybh    ebh    beizhu    ybh    ebh    level
----五华区    0005    0002    五华区    0005    0005    0
  ----西园路192号    0006    0005    西园路192号    0006    00050006    1
    ----金色梧桐3-702    0010    0006    金色梧桐3-702    0010    000500060010    2
      ----昆明越科时空科技有限公司    0011    0010    昆明越科时空科技有限公司    0011    0005000600100011    3
*/
  


/*
标题:查询各节点的父路径函数
作者:爱新觉罗·毓华(十八年风雨,守得冰山雪莲花开)  
时间:2008-05-12
地点:广东深圳
*/

/*
原始数据及要求结果如下:
--食品 
  --水果 
    --香蕉 
    --苹果    
  --蔬菜 
    --青菜
id          pid         name                 
----------- ----------- -------------------- 
1           0           食品
2           1           水果
3           1           蔬菜
4           2           香蕉
5           2           苹果
6           3           青菜

要求得到各节点的父路径即如下结果:
id  pid name  路径                         
--- --- ----- ---------------
1   0   食品  食品
2   1   水果  食品,水果
3   1   蔬菜  食品,蔬菜
4   2   香蕉  食品,水果,香蕉
5   2   苹果  食品,水果,苹果
6   3   青菜  食品,蔬菜,青菜 
*/

create table tb (id int , pid int , name nvarchar(20)) 
insert into tb values(1 , 0 , '食品')
insert into tb values(2 , 1 , '水果')
insert into tb values(3 , 1 , '蔬菜')
insert into tb values(4 , 2 , '香蕉')
insert into tb values(5 , 2 , '苹果')
insert into tb values(6 , 3 , '青菜')
go

--查询各节点的父路径函数
create function f_pid(@id int) returns varchar(100)
as
begin
  declare @re_str as varchar(100)
  set @re_str = ''
  select @re_str = name from tb where id = @id
  while exists (select 1 from tb where id = @id and pid <> 0)
    begin
      select @id = b.id , @re_str = b.name + ',' + @re_str from tb a , tb b where a.id = @id and a.pid = b.id
    end
  return @re_str
end
go

select * , dbo.f_pid(id) 路径 from tb order by id

drop table tb
drop function f_pid

#19


id parentid,score
1,'',130(10+30+30+50),
2,'1',60(30+30)
3,'2',30
4,'1',50
5,'',40(10+30)
6,'5',30


我要的结果是这样。

#20


小F兄。。

深度排序我有了解过,,
但今天的情况不一样咯。

#21


呵呵 我不是很会 SORRY

#22


引用 21 楼 fredrickhu 的回复:
呵呵 我不是很会 SORRY


别这样咯~~

#23


引用 5 楼 happyflystone 的回复:
你要什么结果 ,只要根? 还是任意节点?


id parentid,score 
1,'',130(10+30+30+50), 
2,'1',60(30+30) 
3,'2',30 
4,'1',50 
5,'',40(10+30) 
6,'5',30 

我要的结果是这样。

#24


引用 19 楼 yygyogfny 的回复:
id parentid,score
1,'',130(10+30+30+50),
2,'1',60(30+30)
3,'2',30
4,'1',50
5,'',40(10+30)
6,'5',30

我要的结果是这样。


这个找石头哥帮你搞定。

#25


;with liang as
(
    select *,total = score from tbTest as a
    where not exists(select * from tbTest where a.id = parentid)
    union all
    select a.*,cast(b.total + a.score as decimal(18,2))
    from tbTest as a
       join liang as b
    on a.id = b.parentid
)
select a.id,a.parentid,isnull(b.score,a.score) as score
from tbTest as a
   left join (select id,parentid,sum(total) as score 
              from liang group by id,parentid) as b
on a.id=b.id and a.parentid=b.parentid

#26


引用 25 楼 liangck 的回复:
SQL code;with liangas
(select*,total= scorefrom tbTestas awherenotexists(select*from tbTestwhere a.id= parentid)unionallselect a.*,cast(b.total+ a.scoreasdecimal(18,2))from tbTestas ajoin liangas bon ¡­



小梁P,果然厉害,,把统计移到外层,,我咋没有想到呢。。 有关sql树型结构统计的问题:

#27


引用 26 楼 yygyogfny 的回复:
引用 25 楼 liangck 的回复:
SQL code;with liangas
(select*,total= scorefrom tbTestas awherenotexists(select*from tbTestwhere a.id= parentid)unionallselect a.*,cast(b.total+ a.scoreasdecimal(18,2))from tbTestas ajoin liangas bon ¡­



小梁P,果然厉害,,把统计移到外层,,我咋没有想到呢。。
有关sql树型结构统计的问题:

#28


#29


引用 25 楼 liangck 的回复:
SQL code;with liangas
(select*,total= scorefrom tbTestas awherenotexists(select*from tbTestwhere a.id= parentid)unionallselect a.*,cast(b.total+ a.scoreasdecimal(18,2))from tbTestas ajoin liangas bon ¡­

的确不错.

#30



双编号逐级汇总
if OBJECTPROPERTY(object_id('tb'),'isusertable')<>0 
  drop table tb
  go
create table tb(ybh nvarchar(10),ebh nvarchar(10),beizhu nvarchar(1000),num decimal(14,2))
go
insert tb
select '0001',null,'云南省',100
union all select '0002','0001','昆明市',200
union all select '0003','0001','昭通市',300.3
union all select '0009','0001','大理市',400.4
union all select '0008',null,'四川省',500.5
union all select '0004',null,'贵州省',600.6
union all select '0005','0002','五华区',101.1
union all select '0007','0003','水富县',102.1
union all select '0006','0005','西园路192号',202.1
union all select '0010','0006','金色梧桐3-702',202.2
union all select '0011','0010','昆空科技有限公司',303.1
union all select '0015','0007','两碗乡',303.2
union all select '0013','0015','两碗村',303.4
union all select '0012','0013','某跨国集团董事',444.1
union all select '0014','0008','成都市',111.10






declare @level_tt table(ybh nvarchar(1000),ebh nvarchar(1000),level int)
  declare @level int
  set @level=0
  insert @level_tt(ybh,ebh,level)
  select ybh,ybh,@level from tb where ebh is null
  while @@ROWCOUNT>0
  begin 
          set @level=@level+1
          insert @level_tt(ybh,ebh,level)
          select a.ybh,b.ebh+a.ybh,@level
            from tb a,@level_tt b
            where a.ebh=b.ybh and b.level=@level-1
 end
select a.ybh,a.ebh,a.beizhu,a.num,SUM(a.num) as 汇总
  from tb a,@level_tt b,tb c,@level_tt d
  where a.ybh=b.ybh and c.ybh=d.ybh
        and d.ebh like b.ebh+'%'
  group by a.ybh,a.ebh,a.beizhu,a.num
  order by a.ebh
  
  /*
  ybh ebh beizhu num 汇总
0001 NULL 云南省 100.00 1200.00
0004 NULL 贵州省 600.60 600.60
0008 NULL 四川省 500.50 1001.00
0002 0001 昆明市 200.00 1000.00
0003 0001 昭通市 300.30 1501.50
0009 0001 大理市 400.40 400.40
0005 0002 五华区 101.10 404.40
0007 0003 水富县 102.10 408.40
0006 0005 西园路192号 202.10 606.30
0010 0006 金色梧桐3-702 202.20 404.40
0015 0007 两碗乡 303.20 909.60
0014 0008 成都市 111.10 111.10
0011 0010 昆空科技有限公司 303.10 303.10
0012 0013 某跨国集团董事 444.10 444.10
0013 0015 两碗村 303.40 606.80
*/
这样行吗?

#31


CREATE TABLE tbTest --drop table tbtest
(id nvarchar(5), 
parentID nvarchar(5), 
score decimal(18,2) 


insert into tbTest 
select '01','',10 
union all 
select '02','01',30 
union all 
select '03','02',30 
union all 
select '04','01',50 
union all 
select '05','',10 
union all 
select '06','05',30 



declare @level_tt table(id nvarchar(1000),parentID nvarchar(1000),level int)
  declare @level int
  set @level=0
  insert @level_tt(id,parentID,level)
  select id,id,@level from tbTest where isnull(parentID,'')=''  
  while @@ROWCOUNT>0
  begin 
          set @level=@level+1
          insert @level_tt(id,parentID,level)
          select a.id,cast(b.parentID as varchar)+cast(a.id as varchar),@level
            from tbTest a,@level_tt b
            where a.parentID=b.id and b.level=@level-1
 end
 select * from @level_tt
select a.id,a.parentID,a.score,SUM(c.score) as 汇总
  from tbTest a,@level_tt b,tbTest c,@level_tt d
  where a.ID=b.ID and c.ID=d.ID
        and d.parentID like b.parentID+'%'
  group by a.ID,a.parentID,a.score
  order by a.parentID
  
 /*
 id parentID score 汇总
01 10.00 120.00
05 10.00 40.00
02 01 30.00 60.00
04 01 50.00 50.00
03 02 30.00 30.00
06 05 30.00 30.00
*/
这样就对了

#32


厉害,学习.

#33


再定义一个中间表。记录父子关系,每次统计的时候从中间表中查询所有子节点记录,然后再统计。希望这个思路可以帮到你。

例如:
CREATE TABLE tbTestPath 
(id nvarchar(5), 
parentID nvarchar(5)

-------------------------------------------
构建如下数据:
id      parentid
1 1
2 1
3 1
3 2
4 1
5 5
6 5
2 2
3 3
4 4
6 6


select sum(score),parentid from (select tbTest.score ,tbTestPath.*from tbTest inner join tbTestPath on tbTest.id=tbTestPath.id) as a group by a.parentID

#34


学习

#35


进来学习

#36


参看:
使用SQL Server 2008中的hierarchyid类型来设计具有树型层次关系的表
http://blog.csdn.net/tjvictor/archive/2009/07/30/4395681.aspx

SQL Server中如何存储具有层次关系的表
http://blog.csdn.net/tjvictor/archive/2009/07/30/4395677.aspx

#37


引用 23 楼 yygyogfny 的回复:
引用 5 楼 happyflystone 的回复:
 你要什么结果 ,只要根? 还是任意节点?


 id parentid,score
 1,'',130(10+30+30+50),
 2,'1',60(30+30)
 3,'2',30
 4,'1',50
 5,'',40(10+30)
 6,'5',30

 我要的结果是这样。


10+30+30+50 结果不是120吗?130怎么出来的,我纠结了好久。

#38


同意楼上,我也想知道130是怎么算出来的?希望赐教!

#39


好...........

#40


好............