我在表格中有这个树层次结构。每个节点一行。 我想显示树中每个节点的子计数。 结果将是:
ID COUNT
100 9
129 5
439 3
450 1
501 2
602 1
134 3
133 2
表架构:
Table - Organization_structure
orgID
parentID
Table - Organization_detail
RID (PK)
OrganizationID
ParentOrganizationID
data:
orgID parrent ID
602 501
501 439
450 129
439 129
129 100
133 134
134 100
RID OrganizationID ParentOrganizationID
1 100 top
2 129 100
3 439 129
4 450 129
5 501 439
6 602 501
7 134 100
8 133 134
9 133 134
任何帮助如何实现这一目标?最好的SQL服务器。
答案 0 :(得分:0)
这有点复杂,因为您应该使用递归查询,然后我使用了CROSS APPLY联接来计算记录:
我已经设置了下一个示例,(在您发布数据之前)
CREATE TABLE Organization_structure (orgID int, parentID int);
INSERT INTO Organization_structure VALUES
(100, NULL),
(129, 100),
(134, 100),
(439, 129),
(450, 129),
(133, 134),
(133, 134),
(501, 439),
(602, 501);
这是我的解决方案:
with tree as
(
select orgId, parentId,0 as tree_order, path = cast('root' as varchar(100))
from Organization_structure
where parentID is null
union all
select os.orgId, os.parentId, 1 + tree_order as tree_order,
path = cast(tree.path + '/' + right(('000000000' + os.orgId), 10) as varchar(100))
from Organization_structure os
join tree
on tree.orgId = os.parentId
)
select orgId, tree_order, path, t2.cnt
from tree
cross apply (select count(*) cnt from tree t1 where t1.path like tree.path + '%') t2
order by tree_order;
这就是结果:
orgId | tree_order | path | cnt ----: | ---------: | :------------------- | --: 100 | 0 | root | 9 129 | 1 | root/129 | 5 134 | 1 | root/134 | 3 133 | 2 | root/134/133 | 2 133 | 2 | root/134/133 | 2 439 | 2 | root/129/439 | 3 450 | 2 | root/129/450 | 1 501 | 3 | root/129/439/501 | 2 602 | 4 | root/129/439/501/602 | 1
dbfiddle here
答案 1 :(得分:0)
如果您将数据转换为hierarchyid
,则可以使用IsDescendantOf
方法获取这些数据。可能有一种更简单的方法,但这是我的第一个想法。第一部分是格式化hierarchyid的数据。
计数魔法出现在我找到所有节点的地方,这些节点是当前节点的后代。通过对orgid
进行分组,您可以获得所有后代的计数。
with data (OrgId, ParentOrgId) as
(
select 100, null union all
select 129, 100 union all
select 134, 100 union all
select 133, 134 union all
select 135, 134 union all
select 439, 129 union all
select 450, 129 union all
select 501, 439 union all
select 602, 501
), cte as
(
select
sPath = cast(concat('/', OrgId, '/') as varchar(max)),
Path = hierarchyid::Parse(concat('/', OrgId, '/')),
PreviousPath = hierarchyid::GetRoot(),
OrgId,
ParentOrgId
from data
where ParentOrgId is null
union all
select
sPath = cast(concat(c.sPath, s.OrgId, '/') as varchar(max)),
Path = hierarchyid::Parse(concat(c.sPath, s.OrgId, '/')),
PreviousPath = c.Path,
OrgId = s.OrgId,
ParentOrgId = s.ParentOrgId
from cte c
inner join data s
on c.OrgId = s.ParentOrgId
)
select a.OrgId, NumChildren = count(1)
from cte a
inner join cte b
on b.Path.IsDescendantOf(a.Path) = 1
group by a.OrgId
在构建hierarchyid
路径的同时,您甚至可以在CTE中检查后代中的运行总计。