分层组织的递归平均值

时间:2015-06-20 12:44:20

标签: sql-server recursion common-table-expression reportbuilder3.0

我需要计算分层组织的平均值。 每个学生都可以在不同科目中取得成绩(并非所有学生都有所有科目的成绩),每个学生都有一个家长(这是一个单元)。每个单位都有一个父母,这是另一个单位,依此类推。层次结构树中的分支数量未知(这就是为什么我认为我需要递归方法)。此外,主题的数量是未知的,所以我不能使用任何类似枢轴的技术来理解我。
我的最终目标是使用报表生成器中的Matrix和递归父级功能可视化层次结构,以创建层次结构。

对于持有学生的每个单元,我需要计算每个科目的平均值。对于每个持有单位的单位,我需要计算每个主题的子单位的平均值(意味着平均值)。

我试图采用@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

1 个答案:

答案 0 :(得分:1)

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

;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