--地区表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。
-- 辽宁省 ?
-- 吉林省 ?
-- 沈阳市 ?
-- 大连市 ?
-- 长春市 ?
-- 四平市 ?
-- 沈河区 ?
-- 和平区 ?
-- 大东区 ?
-- 中山区 ?
-- 西岗区 ?
-- 朝阳区 ?
-- 南关区 ?
-- 铁东区 ?
-- 铁西区 ?
CTE 应该能够解决这个问题。你GOOGLE一下吧,我也懒得帮你写出来了。
获取一个地区的全部子及地区 我会写(就像下面这样 ) 但上面的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
@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
大致上是这样的,你简单调下错应该就行了。
这种事情我会加一个LV,把尽量多的操作放到程序中
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
这只是每个区域的项目数量 没有包括全部子孙区域的 项目数量。。。
@sdns: 不好意思,刚才没看清楚,要包含子区域写SQL就很复杂了,建议用存储过程,或者在程序中统计
再等等,看有高手能解决不,如果没有了, 我就sql求出每个区域的项目数量,然后在程序遍历每个区域,再递归查找每个区域的全部子区域的数量加和。
http://www.cnblogs.com/smailxiaobai/archive/2012/01/16/2323291.html
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表 自行测试---
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
求得每个父节点下的直接点数。
Question
在设计ASP.NET网站时,无限分级的商品分类或者论坛板块都可以使用树结构表示,存放到关系型数据库时大家也懂得用Id和ParentId两个字段来表示节点间的关系。
然而这种最省存储空间的表示方法却不是最有效率的,在需要查询指定深度节点时就会遇到问题。我们需要通过递归来逐层展开才能获取到所有该层的节点,然后再在其中进行查询实在既浪费时间又浪费空间。那么有没有更好的做法呢?
Answer
通常在设计表示树结构的数据表时,我们会增加两个字段:
在对树进行操作时,我们还是如平常一样对表执行CRUD操作,要维护这两个字段并不需要费多少力气,然而在查询时却会为我们带来极大的便利。例如要查询第3层的节点,则只需要使用"WHERE Depth = 3";又例如要查询A1节点下B3节点下C2节点下的所有子节点,则可以使用"WHERE Path LIKE 'A1/B3/C2%'"。
这样做的道理就在于,通过增加冗余信息来提高检索速度,同时这些冗余信息非常容易维护所以不容易因为操作不慎而导致信息不一致。设想一下你要对树增加/移动/删除一个节点,原本一条SQL语句就能完成的事情现在还是一条SQL语句就能完成,就算不依赖事务也绝对不会导致信息不一致。
明白了这个道理,我们就可以进行推广,例如我们既可能需要根据Id字段的路径来查询,又可能需要根据Name字段的路径来查询,那就分开IdPath和NamePath两个字段来表示两组路径字符串。
我的意思是没必要递归,适当的冗余会提高查询效率。