【问题标题】:Recursive average for hierarchical organization分层组织的递归平均
【发布时间】:2015-06-20 12:44:19
【问题描述】:

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

对于每个包含学生的单元,我需要计算每个科目的平均值。对于每个包含单元的单元,我需要计算每个科目的子单元的平均值(平均值的平均值)。

我正在尝试按照@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得到所有的信息,再做聚合?
  • 如果您查看我对上一个问题的回答,您应该能够获得计算到层次结构的金额:stackoverflow.com/a/30831821/4420967您只需要计算平均值而不是拆分事件的数据
  • 另外,您确定要取平均值而不是下面单位的实际平均值吗?
  • @JamesZ 我尝试使用您对该问题的出色解决方案,但我确实需要平均值的平均值,并且您的解决方案对实体的所有儿子(直接和直接)的数据求和。我不知道在这种情况下如何使用它。
  • 以前的解决方案适用于整个层次结构中的实际平均成绩,但是平均数是不可能的,或者至少我还没有弄清楚如何做到这一点。可能是它需要基于循环/迭代的解决方案。表,如果您没有大量数据,这还不错

标签: sql-server recursion common-table-expression reportbuilder3.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

【讨论】:

  • 非常感谢,现在将对此进行调查。我自己尝试了迭代方法,有人愿意在我的代码中发现语法问题吗?暂时没有运行。
  • 你从这里缺少集合 "set @level = \@level - 1"
猜你喜欢
  • 2022-06-12
  • 2013-07-30
  • 2014-04-07
  • 2020-02-03
  • 1970-01-01
  • 2015-01-15
  • 1970-01-01
  • 1970-01-01
  • 2019-09-24
相关资源
最近更新 更多