使用先前记录作为变量计算移动平均值

时间:2016-10-17 13:53:28

标签: sql sql-server tsql

我想计算一个列的移动平均值,这需要使用前一个记录中的参数进行算术计算。

我有抄表X的记录,有日期,我想进行计算 使用公式确定平均费率

(reading x - reading y)/(reading date @ x - reading date @ y) 

其中Y始终是前一记录的读数。 DATEDIFF就在几天之内。

  Meter | Reading |    Date
 -------+---------+------------
    1   |  39,000 | 1 Jan 2016
    1   |  39,200 | 1 Feb 2016
    1   |  39,300 | 1 Mar 2016

我想要一个插入计算字段的附加列, 它必须从最新记录中读取,并向后处理 - 因为我有2年的读数,而不是第一次。

Meter | Reading |     Date   |      Rate
------+---------+------------+--------------------
  1   |  39,000 | 1 Aug 2016 | (200 / 31) = 6.45
  1   |  39,200 | 1 Sep 2016 | (100 / 30) = 3.33
  1   |  39,300 | 1 Oct 2016 | Z

我想将此选择到表格中进行报告。

- 编辑 -

我得到了Divide 0错误并决定计算阅读X - 单独阅读Y作为ReadingDiff。

LEAD(MeterReading, 1, 0) OVER (PARTITION BY MeterID ORDER BY MeterReading) - MeterReading AS MeterDiff

因为选择列表中有超过1个MeterID,我如何阻止它计算MeterID 1的最后一个记录和MeterID 2的第一个记录之间的MeterDiff?我不能将每个MeterID的第一条记录设置为0吗?

1 个答案:

答案 0 :(得分:4)

这将是这样的:

select t.*,
       ( (reading - lag(reading) over (partition by meter order by date)) /
         nullif(datediff(day, lag(date) over (partition by meter order by date), date), 0)
       )
from t;

如果读取是整数,那么要小心,因为SQL Server会进行整数除法。所以,你可能想要:

select t.*,
       ( (1.0*reading - lag(reading) over (partition by meter order by date)) /
         nullif(datediff(day, lag(date) over (partition by meter order by date), date), 0)
       )
from t;

注意:lag()是自2012版以来在SQL Server中实现的ANSI标准功能。在此之前,您需要使用计算量更大的方法,例如outer apply