首页 新闻 会员 周边

求助一个树形结构分组求数量的sql,求助!!!

0
悬赏园豆:200 [待解决问题]

--地区表Area

--结构如下

--Id      AreaName    ParentId

--主键   地区名称         父及Id

 

--地区表数据为无限级,数据如下

Id      AreaName    ParentId 

--1       辽宁省           0

--2       吉林省           0

--3       沈阳市           1

--4       大连市           1

--5       长春市           2

--6       四平市           2

--7       沈河区           3

--8       和平区           3

--9       大东区           3

--10      中山区           4

--11      西岗区       4

--12      朝阳区       5

--13      南关区       5

--14      铁东区       6

--15      铁西区       6

 

--项目表

--结构如下

--Id      ProjectName    AreaId

--主键   项目名称      所属地区Id

 

--想得到如下列表

--  地区名称  项目数量(这里的数量是包括全部子及地区的项目的数量,比如辽宁省后面的数量就是辽宁省+沈阳市+大连市+沈河区+和平区+大东区+中山区+西岗区的项目的数量,沈阳市后面的数量就是沈阳市+沈河区+和平区+大东区的项目数量,沈河区就是沈河区的项目数量)  求sql。

--  辽宁省     ?

--  吉林省     ?

--  沈阳市     ?

--  大连市     ?

--  长春市     ?

--  四平市     ?

--  沈河区     ?

--  和平区     ?

--  大东区     ?

--  中山区     ?

--  西岗区     ?

--  朝阳区     ?

--  南关区     ?

--  铁东区     ?

--  铁西区     ?

sdns的主页 sdns | 初学一级 | 园豆:1
提问于:2015-01-23 09:58
< >
分享
所有回答(7)
0

CTE 应该能够解决这个问题。你GOOGLE一下吧,我也懒得帮你写出来了。

爱编程的大叔 | 园豆:30839 (高人七级) | 2015-01-23 10:03

获取一个地区的全部子及地区 我会写(就像下面这样 )  但上面的sql  我还是写不出来

with a as(
select * from Area where Id = '{0}'
    union all select a1.* from a
    inner join Area a1 on a.Id = a1.ParentId
) select * from a

支持(0) 反对(0) sdns | 园豆:1 (初学一级) | 2015-01-23 10:10

@sdns: 

Select k.ProjectName, sum(ProjectCount) as Projectcount from
(With CTE as (
Select  id,Projectname,ParentID, 1 as Projectcount
    from tablename
UNION ALL
Select id, Projectname, ParentID, 1 as Projectcount
    from tablename x
    inner join CTE
    on x.parentid=CTE.id
)
Select a.ProjectName, Projectcount) k
group by ProjectName

大致上是这样的,你简单调下错应该就行了。

支持(0) 反对(0) 爱编程的大叔 | 园豆:30839 (高人七级) | 2015-01-23 11:07
0

这种事情我会加一个LV,把尽量多的操作放到程序中

吴瑞祥 | 园豆:29449 (高人七级) | 2015-01-23 10:16
0
select b.AreaName,a.total from(
select AreaId,count(AreaId) as total from Project group by AreeaId
) a inner join Area b on a.AreaId=b.Id
psforever | 园豆:461 (菜鸟二级) | 2015-01-23 10:17

这只是每个区域的项目数量 没有包括全部子孙区域的 项目数量。。。

支持(0) 反对(0) sdns | 园豆:1 (初学一级) | 2015-01-23 10:20

@sdns: 不好意思,刚才没看清楚,要包含子区域写SQL就很复杂了,建议用存储过程,或者在程序中统计

支持(0) 反对(0) psforever | 园豆:461 (菜鸟二级) | 2015-01-23 10:21

再等等,看有高手能解决不,如果没有了, 我就sql求出每个区域的项目数量,然后在程序遍历每个区域,再递归查找每个区域的全部子区域的数量加和。

支持(0) 反对(0) sdns | 园豆:1 (初学一级) | 2015-01-23 10:25
0

http://www.cnblogs.com/smailxiaobai/archive/2012/01/16/2323291.html

刘宏玺 | 园豆:14020 (专家六级) | 2015-01-23 10:38
0
with cte as
(
    SELECT 
        *
       ,levelId = id 
    FROM test1 
    UNION all
    
    SELECT 
        t1.*
       ,t2.levelId 
    FROM test1 t1 JOIN cte t2 ON t2.id = t1.pid 
 ) 

SELECT 
    *
   ,COUNT = ( 
        SELECT 
            COUNT(test2.name) 
        FROM cte 
        LEFT JOIN test2 
            ON test2.areaId = cte.id 
        WHERE 
            levelId = test1.id 
     ) 
FROM test1


test1 = Area表
test2 = Proj表

自行测试---
幻天芒 | 园豆:37175 (高人七级) | 2015-01-23 11:06
0
1 with a as (select parentid,count(id) num from area group by parentid)
2 select * from a x inner join area y on x.parentid=y.id
View Code

求得每个父节点下的直接点数。

leerh | 园豆:207 (菜鸟二级) | 2015-01-23 11:39
0

Question

在设计ASP.NET网站时,无限分级的商品分类或者论坛板块都可以使用树结构表示,存放到关系型数据库时大家也懂得用Id和ParentId两个字段来表示节点间的关系。

然而这种最省存储空间的表示方法却不是最有效率的,在需要查询指定深度节点时就会遇到问题。我们需要通过递归来逐层展开才能获取到所有该层的节点,然后再在其中进行查询实在既浪费时间又浪费空间。那么有没有更好的做法呢?

Answer

通常在设计表示树结构的数据表时,我们会增加两个字段:

  • Depth - 表示当前节点的深度的整数
  • Path - 表示从根节点到当前节点的路径的字符串,采用节点名称不可能出现的字符作为分隔符

在对树进行操作时,我们还是如平常一样对表执行CRUD操作,要维护这两个字段并不需要费多少力气,然而在查询时却会为我们带来极大的便利。例如要查询第3层的节点,则只需要使用"WHERE Depth = 3";又例如要查询A1节点下B3节点下C2节点下的所有子节点,则可以使用"WHERE Path LIKE 'A1/B3/C2%'"。

这样做的道理就在于,通过增加冗余信息来提高检索速度,同时这些冗余信息非常容易维护所以不容易因为操作不慎而导致信息不一致。设想一下你要对树增加/移动/删除一个节点,原本一条SQL语句就能完成的事情现在还是一条SQL语句就能完成,就算不依赖事务也绝对不会导致信息不一致。

明白了这个道理,我们就可以进行推广,例如我们既可能需要根据Id字段的路径来查询,又可能需要根据Name字段的路径来查询,那就分开IdPath和NamePath两个字段来表示两组路径字符串。

我的意思是没必要递归,适当的冗余会提高查询效率。

Cat Qi | 园豆:761 (小虾三级) | 2015-01-26 17:16
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册