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

标签 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

我想将其选入表格进行报告。

-- 编辑--

我收到除以 0 的错误,因此决定将读数 X - 读数 Y 单独计算为读数差异。

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

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

最佳答案

应该是这样的:

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.

关于sql - 使用先前记录作为变量计算移动平均线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40088272/

相关文章:

sql-server - 使用 hilo 生成器和 sql server 的 Id 主键列应使用什么数据类型?

sql - 事务处理 SQL : Display two SUM() from differents tables?

sql - 来自完整加载表的 Valid_from Valid_to

mysql - 如何将列分组到包含数据的字段中?

php - MySQL 中使用 IF-ELSE 的条件连接语句

c# - 将数据从 DataTable 传输到 Access 数据库时出现 Insert INTO 错误

SQL存储过程问题

SQL 创建 UDF 计算列

sql-server - 在存在语句中使用表变量

sql-server - 存储过程返回值