我正在尝试通过导航层次结构来执行一些计算。在下面的简单示例中,组织具有人数,并且可以与上级组织关联,该人数仅为“叶子”组织指定。我想使用简单的规则来计算层次结构中的人员总数:父级人员总数=子级人员总数。我喜欢为此使用SQL Common Table Expression的想法,但这并不完全有效。确定级别是有效的(因为它遵循自然的自上而下的导航顺序),但不是确定人数。您将如何解决此问题,或者有更好的方法来自下而上地执行此计算?
-- Define the hierachical table Org
drop table if exists Org
create table Org (
ID int identity (1,1) not null, Name nvarchar(50), parent int null, employees int,
constraint [PK_Org] primary key clustered (ID),
constraint [FK_Parent] foreign key (parent) references Org(ID)
);
-- Fill it in with a simple example
insert into Org (name, parent, employees) values ('ACME', NULL, 0);
insert into Org (name, parent, employees) values ('ACME France', (select Org.ID from Org where Name = 'ACME'), 0);
insert into Org (name, parent, employees) values ('ACME UK', (select Org.ID from Org where Name = 'ACME'), 0);
insert into Org (name, parent, employees) values ('ACME Paris', (select Org.ID from Org where Name = 'ACME France'), 200);
insert into Org (name, parent, employees) values ('ACME Lyons', (select Org.ID from Org where Name = 'ACME France'), 100);
insert into Org (name, parent, employees) values ('ACME London', (select Org.ID from Org where Name = 'ACME UK'), 150);
select * from Org;
-- Try to determine the total number of employees at any level of the hierarchy
with Orgs as (
select
ID, name, parent, 0 as employees, 0 as level from Org where parent is NULL
union all
select
child.ID, child.name, child.parent, Orgs.employees + child.employees, level + 1 from Org child
join Orgs on child.parent = Orgs.ID
)
select * from Orgs;
此查询返回:
确定级别是正确的,但人员总数的计算不正确(在层次结构的顶部,英国应该是150,法国300和450)。看来CTE适合自上而下的导航,但不适合自下而上的导航?
谢谢!JP
您需要遍历每个非叶节点的层次结构,并对来自该节点的所有路径求和。
with Orgs as (
select
id as [top], ID, name, parent, 0 as employees, 0 as level
from Org g
where exists (select 1 from Org g2 where g.ID = g2.parent)
union all
select
orgs.[top], child.ID, child.name, child.parent, Orgs.employees + child.employees, level + 1 from Org child
join Orgs on child.parent = Orgs.ID
)
select [top] as id, sum(employees) employees
from Orgs
group by [top];
尝试一下:/ *****数据************* /
-- Define the hierachical table Org
drop table Org
create table Org (
ID int identity (1,1) not null, Name nvarchar(50), parent int null, employees int,
constraint [PK_Org] primary key clustered (ID),
constraint [FK_Parent] foreign key (parent) references Org(ID)
);
-- Fill it in with a simple example
insert into Org (name, parent, employees) values ('ACME', NULL, 0);
insert into Org (name, parent, employees) values ('ACME France', (select Org.ID from Org where Name = 'ACME'), 0);
insert into Org (name, parent, employees) values ('ACME UK', (select Org.ID from Org where Name = 'ACME'), 0);
insert into Org (name, parent, employees) values ('ACME Paris', (select Org.ID from Org where Name = 'ACME France'), 200);
insert into Org (name, parent, employees) values ('ACME Lyons', (select Org.ID from Org where Name = 'ACME France'), 100);
insert into Org (name, parent, employees) values ('ACME London', (select Org.ID from Org where Name = 'ACME UK'), 150);
select * from Org;
/ ********结束数据*********** /
/ ******** QUERY ****** /
-尝试确定层次结构中任何级别的员工总数
with Orgs as (
select
ID, name, parent, employees, ID as RootID, 0 as level from Org
union all
select
child.ID , child.name, child.parent, child.employees, Orgs.RootID, level + 1 from Org child
join Orgs on child.parent = Orgs.ID
)
select Org.Id,
Org.Parent,
Org.Name,
Org.employees,
(select max(level) from Orgs a where a.Id = Org.Id) as [Level],
S.ProductCountIncludingChildren
from Org
inner join (
select RootID,
sum(employees) as ProductCountIncludingChildren
from Orgs
group by RootID
) as S
on Org.Id = S.RootID
left join Org Org2 on Org2.ID = Org.Parent
order by Org.Id
/ ****结束查询****** /