需要根据每个会计周计算成本的平均值

时间:2014-02-06 10:53:20

标签: sql sum average

我希望有人可以帮我解决这个问题,我试图通过以下数据示例计算每周平均值:

    Practice ID      Cost          FiscalWeek
        1            10.00             1
        1            33.00             2
        1            55.00             3
        1            18.00             4
        1            36.00             5
        1            24.00             6
        13           56.00             1
        13           10.00             2
        13           24.00             3
        13           30.00             4
        13           20.00             5
        13           18.00             6

我想要的是按练习ID进行分组,但是计算出每个练习的平均值(这些练习中有超过500个不仅仅是上面的练习ID),并且每周都要练习一次,所以例如在第1周就没有了平均值,但第2周将是第1周和第2周的平均值,然后第3周将是第1,2周和第3周的平均值,然后是第2周。然后我需要通过练习ID和每个财政周来证明这一点。

目前我有一些不漂亮的代码,并且必须有一个更简单的方法,这段代码是:

我将所有数据传递给表变量然后使用CTE然后使用case语句来设置每个星期,如:

  CASE WHEN fiscalweek = 1 THEN cost ELSE 0 END AS [1],
  CASE WHEN fiscalweek = 2 THEN cost ELSE 0 END AS [2],
  CASE WHEN fiscalweek = 3 THEN cost ELSE 0 END AS [3]

这会将第1周的成本带回到它自己的专栏中,例如1,2,3等等,然后我用了第二个CTE来计算每周的列数,所以例如计算出第6周我将使用这个代码:

    sum([1]) as 'Average Wk 1',
    sum([1]+[2])/2 as 'Average Wk 2',
    sum([1]+[2]+[3])/3 as 'Average Wk 3',
    sum([1]+[2]+[3]+[4])/4 as 'Average Wk 4',
    sum([1]+[2]+[3]+[4]+[5])/5 as 'Average Wk 5'
    sum([1]+[2]+[3]+[4]+[5]+[6])/6 as 'Average Wk 6'

我已经考虑过在T-SQL中准确计算出这个平均值的各种不同方法,所以我最终可以将它放到SSRS中。我已经考虑过使用While..Loop,Cursor,但没有看到一个简单的方法。

3 个答案:

答案 0 :(得分:2)

您正在寻找平均值的累积平均值。在支持窗口/分析功能的数据库中,您可以执行以下操作:

select fiscalweek, avg(cost) as avgcost,
       avg(avg(cost)) over (order by fiscalweek) as cumavg
from practices p
group by fiscalweek
order by 1;

如果你没有窗口函数,那么你需要使用某种形式的相关子查询或加入:

select p1.fiscalweek, avg(p1.avgcost)
from (select fiscalweek avg(cost) as avgcost
      from practices p
      group by fiscalweek
     ) p1 join
     (select fiscalweek avg(cost) as avgcost
      from practices p
      group by fiscalweek
     ) p2
     on p12 <= p1
group by p1.fiscalweek
order by 1;

我想提醒您,您正在计算“平均值”。这与累积平均值不同,累计平均值可以计算为:

select fiscalweek, 
      (sum(sum(cost)) over (order by fiscalweek) /
       sum(count(*)) over (order by fiscalweek)
      ) avgcost
from practices p
group by fiscalweek
order by 1;

每周将一个视为最终平均值中的一个数据点(您似乎想要的)。每周其他权重乘以一周内的点数(后一种解决方案)。当数周的点数不同时,这些结果会产生非常不同的结果。

答案 1 :(得分:0)

我认为这样可行:

SELECT t1.pid,
t1.fiscalweek,
(
  SELECT SUM(t.cost)/COUNT(t.cost)
  FROM tablename AS t
  WHERE t.pid = t1.pid
  AND t.fiscalweek <= t1.fiscalweek
) AS average
FROM tablename AS t1
GROUP BY t1.pid, t1.fiscalweek

修改

要考虑没有参赛作品的财政周,您可以简单地交换

SELECT SUM(t.cost)/COUNT(t.cost)

SELECT SUM(t.cost)/t1.fiscalweek

从第1周或

计算
SELECT SUM(t.cost)/(t1.fiscalweek - MIN(t.fiscalweek) + 1)

从这种做法的第一周开始计算。

如果所有练习平均值应该在同一周开始(而不一定是第1周),那么你必须找到所有周数的最小值。

此外,如果您计算多年,这将无效,但我认为这不是他的情况。

答案 2 :(得分:0)

我不知道如果我完全理解这个问题:但尝试执行此操作:应该帮助您:

create table #practice(PID int,cost decimal,Fweek int)
insert into #practice values (1,10,1)
insert into #practice values (1,33,2)
insert into #practice values (1,55,3)
insert into #practice values (1,18,4)
insert into #practice values (1,36,5)
insert into #practice values (1,24,6)
insert into #practice values (13,56,1)
insert into #practice values (13,10,2)
insert into #practice values (13,24,3)
insert into #practice values (13,30,4)
insert into #practice values (13,20,5)
insert into #practice values (13,18,6)

select * from #practice
select pid,Cost,
(select AVG(cost) from #practice p2 where p2.Fweek <= p1.Fweek and p1.pid = p2.pid) WeeklyAVG,
Fweek,AVG(COST) over (Partition by PID)  as PIDAVG
from #practice p1;