通过SQL中的层次结构进行计算

问题描述 投票:0回答:2

我正在尝试通过导航层次结构来执行一些计算。在下面的简单示例中,组织具有人数,并且可以与上级组织关联,该人数仅为“叶子”组织指定。我想使用简单的规则来计算层次结构中的人员总数:父级人员总数=子级人员总数。我喜欢为此使用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;

此查询返回:

enter image description here

确定级别是正确的,但人员总数的计算不正确(在层次结构的顶部,英国应该是150,法国300和450)。看来CTE适合自上而下的导航,但不适合自下而上的导航?

谢谢!JP

sql sql-server hierarchy
2个回答
0
投票

您需要遍历每个非叶节点的层次结构,并对来自该节点的所有路径求和。

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];

Db fiddle


0
投票

尝试一下:/ *****数据************* /

-- 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

/ ****结束查询****** /

© www.soinside.com 2019 - 2024. All rights reserved.