SQL Server中7天滚动平均值的SQL查询

时间:2014-09-18 21:08:38

标签: sql sql-server moving-average

我有一个每小时产品使用情况表(产品使用次数)数据 -

ID (bigint)| ProductId (tinyint)| Date (int - YYYYMMDD) | Hour (tinyint)| UsageCount (int)
#|1 | 20140901 | 0 | 10
#|1 | 20140901 | 1 | 15
#|1 | 20140902 | 5 | 25
#|1 | 20140903 | 5 | 25
#|1 | 20140904 | 3 | 25
#|1 | 20140905 | 7 | 25
#|1 | 20140906 | 10 | 25
#|1 | 20140907 | 9 | 25
#|1 | 20140908 | 5 | 25
#|2 | 20140903 | 16 | 10
#|2 | 20140903 | 13 | 115

同样,我在product_usage表中每小时存储4种不同产品(ProductId从1到4)的使用数据。可以想象,随着夜间ETL过程转储整个前一天的数据,它会不断增长。如果某一天中的任何一小时都未使用该产品,则该表中的记录将不会显示在该表中。同样,如果产品一整天都没有使用,那么表中当天就不会有任何记录。我需要生成一份报告,提供每日使用情况和过去7天的滚动平均值 -

例如:

ProductId | Date | DailyUsage | RollingAverage
1 | 20140901 | sum of usages of that day | (Sum of usages from 20140901 through 20140826) / 7
1 | 20140901 | sum of usages of that day | (Sum of usages from 20140901 through 20140826) / 7
1 | 20140902 | sum of usages of that day | (Sum of usages from 20140902 through 20140827) / 7
2 | 20140902 | sum of usages of that day | (Sum of usages from 20140902 through 20140827) / 7

等等...... 我打算在SQL Server 2014中创建一个索引视图。你能想到一个有效的SQL查询吗?

2 个答案:

答案 0 :(得分:16)

尝试:

select x.*,
       avg(dailyusage) over(partition by productid order by productid, date rows between 6 preceding and current row) as rolling_avg
  from (select productid, date, sum(usagecount) as dailyusage
          from tbl
         group by productid, date) x

<强>小提琴:

http://sqlfiddle.com/#!6/f674a7/4/0

替换&#34; avg(dailusage)结束....&#34;如果您真正想要的是过去一周的总和,则用总和(而不是平均值)。在你的标题中,你说你想要平均值,但后来你说你想要总和。查询应该是相同的,所以请使用您真正想要的。

正如Gordon所指出的,这基本上是过去6个使用产品的日期的平均值,如果有几天没有任何产品在桌面上,因此可能不仅仅是过去的6天,因为它根本没用过。为了解决这个问题,你可以使用日期表和产品表。

答案 1 :(得分:4)

如果您可能在某些日子丢失数据,则必须小心。如果我假设每天都有某些产品的数据,那么这种方法将起作用:

select p.productid, d.date, sum(usagecount),
       sum(sum(usagecount)) over (partition by p.productid order by d.date
                                  rows between 6 preceding and current row) as Sum7day
from (select distinct productid from hourly) p cross join
     (select distinct date from hourly) d left join
     hourly h
     on h.productid = p.productid and h.date = p.date
group by p.productid, d.date;