Sql server T-SQL Server 2014中使用分析函数的移动平均值

Sql server T-SQL Server 2014中使用分析函数的移动平均值,sql-server,tsql,sql-server-2014,moving-average,analytic-functions,Sql Server,Tsql,Sql Server 2014,Moving Average,Analytic Functions,我需要根据一些质量标准,计算一组大样本数据的每周和每月每天每个传感器的移动平均数。我有一个基于相关子查询(或自联接)的有效解决方案,但我想知道使用分析函数是否可行,是否会产生更好的性能 以下是我现在拥有的(简化): 我尝试用下面的代码片段替换weekly average的子查询,但它显然无法正确处理没有任何样本的天数。我曾想过使用RANGE或partitionby表达式,但我不知道如何指定窗口框架来选择示例,例如“last week” 我甚至考虑过“古怪的更新”,但除了凌乱之外,我认为这几天的平

我需要根据一些质量标准,计算一组大样本数据的每周和每月每天每个传感器的移动平均数。我有一个基于相关子查询(或自联接)的有效解决方案,但我想知道使用分析函数是否可行,是否会产生更好的性能

以下是我现在拥有的(简化):

我尝试用下面的代码片段替换weekly average的子查询,但它显然无法正确处理没有任何样本的天数。我曾想过使用RANGE或partitionby表达式,但我不知道如何指定窗口框架来选择示例,例如“last week”


我甚至考虑过“古怪的更新”,但除了凌乱之外,我认为这几天的平均值没有意义。

查看窗口功能“超前”和“滞后”。它们正是为了这个目的而创建的(在结果集上移动窗口时执行agg函数)。

我的代码编译得更快,扫描更少,逻辑读取更少。对于这样一个小的数据集,很难判断,我没有你的索引等等。所以你自己试试吧。如果有什么区别的话,它比您的查询更简单。现在在我的查询中,平均月份是很棘手的。如果你愿意,你可以像其他人一样使用一定的天数。所以,你可能会做前30天的平均值。我投入的只是当月的平均值。我确实有一种感觉,你可以把你的子查询放进去,但是我没有尝试,因为现在已经很晚了

注意:前面的花哨行假设它们是每天的一行,没有间隔,否则您的数据将被扭曲

SELECT  SensorID,
        SampleDate,
        AVG(avg_VALUE) OVER (PARTITION BY SensorID,SampleDate) avg_per_date, --but I only have one row per date so that's why its a whole number each time
        AVG(avg_VALUE) OVER (PARTITION BY SensorID ORDER BY SampleDate ROWS BETWEEN 7 PRECEDING AND CURRENT ROW)  AverageLastWeek,
        AVG(avg_VALUE) OVER (PARTITION BY SensorID ORDER BY SampleDate ROWS BETWEEN 14 PRECEDING AND CURRENT ROW) AverageLast2Weeks,
        AVG(avg_VALUE) OVER (PARTITION BY SensorID,MONTH(SampleDate) ORDER BY SampleDate ROWS UNBOUNDED PRECEDING) AverageCurrentMonth
        --AVG(avg_VALUE) OVER (PARTITION BY SensorID ORDER BY SampleDate ROWS BETWEEN 30 PRECEDING AND CURRENT ROW) AverageLast30Days --alternatively you could do this
FROM
(
    SELECT SensorId,CAST(SampleTime AS DATE) SampleDate,AVG(Value) Avg_value
    FROM Samples
    WHERE Quality > .95
    GROUP BY SensorId,CAST(SampleTime AS DATE)
) S
ORDER BY SensorID,SampleDate

如果您有任何问题或需要其他任何东西,请告诉我

你能提供一些样本数据吗。这可以通过递归CTE实现。在我有一些测试数据可以使用后,我可以提供帮助

您需要上个月的信息还是每个Id的上个月信息?我正在考虑过滤上个月的采样时间。如果我理解正确,我相信你可以不用使用PIVOT函数。我不确定这会快多少,但绝对值得一试!我需要每个id和每天的移动平均值。例如,在今天的日期,任何给定的Id都会产生一行,每周平均值基于4/30到5/6的样本,每月平均值基于4/7到5/6的样本。因此,窗口框架比步骤或分区要大。实际上,我考虑过由感测器划分的引线/滞后解析函数,但据我所知,它们是基于行计数的,因此不处理没有样本的日子-很像我原来的问题中提到的“行7前”子句。你能给我一个具体的例子来帮助我更好地理解这些函数是如何帮助我的吗?这取决于你是想把“缺失”的天数算作值为0的天数,还是根本不算数。对于0值,可以创建一个“天”表并将其联接,从而用0“填充”偏移量的第个间隙。对于第二个选项,您可以再次创建一个“days”表,并在days.date-X和days.date之间将其与ID上的CTE和CTE.date连接起来。然后您可以计算每个日期的计数和平均值。感谢您提供的具体示例。但是,它与我在原始问题底部提到的代码片段非常相似,只是您的建议没有进行适当的加权平均以正确处理不同样本数的天数。正如你自己指出的,它们都不能处理没有样本的日子,这是一个要求。是的,这就是Windows功能的局限性。解决这个问题的唯一方法是,为每个SensorID创建从最小日期到结束日期的每个数据的列表,然后将其加入到您的表中,这样做并不漂亮。但在这一点上,你做了那么多额外的工作,坚持你所得到的可能会更有效率。
SUM(ValueSum) OVER(PARTITION BY SensorId ORDER BY SampleTime ROWS 7 PRECEDING) / SUM(ValueCount) OVER(PARTITION BY SensorId ORDER BY SampleTime ROWS 7 PRECEDING) AS AverageLastWeek
SELECT  SensorID,
        SampleDate,
        AVG(avg_VALUE) OVER (PARTITION BY SensorID,SampleDate) avg_per_date, --but I only have one row per date so that's why its a whole number each time
        AVG(avg_VALUE) OVER (PARTITION BY SensorID ORDER BY SampleDate ROWS BETWEEN 7 PRECEDING AND CURRENT ROW)  AverageLastWeek,
        AVG(avg_VALUE) OVER (PARTITION BY SensorID ORDER BY SampleDate ROWS BETWEEN 14 PRECEDING AND CURRENT ROW) AverageLast2Weeks,
        AVG(avg_VALUE) OVER (PARTITION BY SensorID,MONTH(SampleDate) ORDER BY SampleDate ROWS UNBOUNDED PRECEDING) AverageCurrentMonth
        --AVG(avg_VALUE) OVER (PARTITION BY SensorID ORDER BY SampleDate ROWS BETWEEN 30 PRECEDING AND CURRENT ROW) AverageLast30Days --alternatively you could do this
FROM
(
    SELECT SensorId,CAST(SampleTime AS DATE) SampleDate,AVG(Value) Avg_value
    FROM Samples
    WHERE Quality > .95
    GROUP BY SensorId,CAST(SampleTime AS DATE)
) S
ORDER BY SensorID,SampleDate