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

Posted

技术标签:

【中文标题】SQL Server 中 7 天滚动平均值的 SQL 查询【英文标题】:SQL Query for 7 Day Rolling Average in SQL Server 【发布时间】:2014-11-13 08:49:01 【问题描述】:

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

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 查询来执行此操作吗?

【问题讨论】:

你所说的“滚动平均”实际上是一个总和。 【参考方案1】:

试试:

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

如果您真正想要的是过去一周的总和,请将“avg(dailusage) over....”替换为 sum(而不是 avg)。在你的标题中你说你想要平均值,但后来你说你想要总和。查询应该与此相同,因此请使用您实际想要的任何一个。

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

【讨论】:

嘿,你知道如何为 msql 2008 改写你的 sql 代码吗?我在 2008 年尝试运行它,但一直出错。 SQL Server 2008 不支持 ROWS BETWEEN 语法。您需要稍微不同的方法,例如***.com/questions/26618353/… 哇——我知道“over(partition ...)”函数的部分功能,但我显然忽略了“preceding”元素。谢谢!【参考方案2】:

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

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;

【讨论】:

没错。如果缺少观察,“排序”和获取最后 N 个观察的技术就会失效。

以上是关于SQL Server 中 7 天滚动平均值的 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

如何从事件日志表计算 SQL Server 中的平均队列长度

在 BigQuery 中滚动 7 天

pandas使用groupby函数计算dataframe数据中每个分组的N个数值的滚动平均值(rolling mean)例如,计算某公司的多个店铺每N天(5天)的滚动销售额平均值

pandas使用groupby函数计算dataframe数据中每个分组的滚动统计值(rolling statistics)的语法:例如分组的N天滚动平均值滚动中位数滚动最大最小值滚动加和等

如何将滚动 7 天和 30 天的列添加到我每天在 SQL Server 中的不同登录次数中

pyspark 时间序列数据的高性能滚动/窗口聚合