分层组织的递归平均

Recursive average for hierarchical organization

我需要计算等级组织的平均值。 每个学生可以有不同科目的成绩(不是所有学生所有科目都有成绩),每个学生都有一个Parent(也就是一个单元)。每个单元都有一个父单元,它是另一个单元,依此类推。层次结构树中的分支数是未知的(这就是为什么我认为我需要递归方法)。此外,受试者的数量是未知的,所以我不能根据我的理解使用任何类似枢轴的技术。
我的最终目标是使用 Report Builder 中的 Matrix 和 Recursive Parent 功能可视化层次结构来创建层次结构。

对于容纳学生的每个单元,我需要计算每个科目的平均值。对于每个持有单位的单位,我需要计算每个科目的子单位的平均值(意思是平均值的平均值)。

我正在尝试按照@JamesZ 的建议采用基于迭代的方法:

insert into temp
select * from UnitsAvg

declare @level int = (select max(level) from hierarchy)

while (@level >= 0)
begin
insert into temp
select h.unitparentid as id, u.subject, avg(AvgGrade) as AvgGrade
from UnitsAvg u
inner join hierarchy h
on u.unitid=h.unitid
where level=@level
group by h.unitparentid, u.subject
@level = @level - 1
end

select * from temp

那里的语法有问题,不胜感激! the fiddle

这是解决问题的基于迭代的方法,也许这会有所帮助,或者其他人可以弄清楚如何在没有循环的情况下进行更新。 CTE 的第一部分是找出层次结构中存在哪些主题。它可能不是最佳的,但它是从 复制到事件问题的,所以别名也有点奇怪 :)

;with CTE as (
  select S.StudentId as UnitID, S.ParentID as UnitParentID,
    S.StudentID, Subject, 'S' as Type
  from grades S
union all
  select U.UnitId, U.UnitParentId, 
    CTE.StudentId as StudentID, Subject, 'U' as Type
  from
    Hierarchy U
    join CTE
      on U.UnitId = CTE.UnitParentId
)
select distinct UnitID, UnitParentId, Subject, -1 as Grade
into #tmp
from CTE
where Type = 'U'

while (1=1) begin
  update #tmp 
  set Grade = (select avg(Grade)
    from (
      select Grade from grades g 
      where g.ParentId = #tmp.UnitID and 
      g.Subject = #tmp.Subject

      union all

      select Grade from #tmp t 
      where t.UnitParentID = #tmp.UnitID and 
      t.Subject = #tmp.Subject
    ) X
  )
  where 
    Grade = -1 and
    not exists (
      select 1 from #tmp t
      where t.UnitParentID = #tmp.UnitID and t.Grade = -1
    )

  if (@@rowcount = 0) break
end

循环更新那些可以更新的单位的值(=它们下面的层次结构已经计算好了)。等级 -1 用于确定该值是否已计算。如果没有要更新的行,则循环结束。如果单元中有子单元和学生,则两者的成绩按相同的权重计算。

SQL Fiddle