使用LAG()计算行之间的差异

时间:2019-08-18 07:03:31

标签: mysql

这个问题类似于SQL Server LAG() function to calculate differences between rows,除了该示例使用DATEDIFF()。假设我有一个表Weather,其中有列RecordDateTemperature。我想选择与前一天相比较高的Temperature对应的行。

例如,如果Weather像这样,

mysql> select * from weather;
+----+------------+-------------+
| id | RecordDate | Temperature |
+----+------------+-------------+
|  5 | 2000-12-16 |           3 |
|  6 | 2000-12-15 |          -1 |
+----+------------+-------------+

我想选择第二天,

+----+------------+-------------+
| id | RecordDate | Temperature |
+----+------------+-------------+
|  5 | 2000-12-16 |           3 |
+----+------------+-------------+

因为那天3的温度高于前一天-1的温度。

我喜欢这个查询,它遵循https://dev.mysql.com/doc/refman/8.0/en/window-function-descriptions.html#function_lag的示例,我快到了:

mysql> select id, recorddate, temperature, 
              lag(temperature) over w as 'lag' 
       from weather 
       window w as (order by recorddate);
+----+------------+-------------+------+
| id | recorddate | temperature | lag  |
+----+------------+-------------+------+
|  6 | 2000-12-15 |          -1 | NULL |
|  5 | 2000-12-16 |           3 |   -1 |
+----+------------+-------------+------+

剩下的就是选择temperature大于lag的行。但是,如果在查询末尾添加where temperature > lag,则会收到语法错误:

mysql> select id, recorddate, temperature, 
              lag(temperature) over w as 'lag' 
       from weather 
       window w as (order by recorddate) 
       where temperature > lag;
  

错误1064(42000):您的SQL语法有错误;检查   与您的MySQL服务器版本相对应的手册   在第1行的“温度>滞后”附近使用的语法

有什么方法可以只维护中间结果中temperature > lag的行吗?

1 个答案:

答案 0 :(得分:2)

解决此问题的一种方法是利用Correlated Subqueries(在MySQL的较早版本中也可以使用)。我们可以使用子查询根据前一个日期获取每行的前一个温度,然后使用self.my_method子句过滤掉当前温度高于前一个温度的情况:

查询#1

HAVING

View on DB Fiddle


仅适用于MySQL 8 + :我们仍然可以使用LAG()函数解决此问题,但不能直接解决。到目前为止,MySQL在SELECT w1.id, w1.recorddate, w1.temperature, (SELECT w2.temperature FROM weather AS w2 WHERE w2.RecordDate < w1.RecordDate ORDER BY w2.RecordDate DESC LIMIT 1) AS prev_temperature FROM weather AS w1 HAVING w1.temperature > prev_temperature; | id | recorddate | temperature | prev_temperature | | --- | ---------- | ----------- | ---------------- | | 5 | 2000-12-16 | 3 | -1 | 子句中抱怨如果我们尝试使用Window函数:

WHERE
  

错误:在这种情况下,您不能使用窗口函数“ lag”。

或者,如果我们尝试计算表达式中的先前温度,并使用SELECT id, RecordDate, temperature FROM weather WHERE temperature > LAG(temperature) OVER (ORDER BY RecordDate); 子句中的别名进行过滤:

HAVING
  

错误:您不能使用表达式的别名“ prev_temperature”   在这种情况下包含一个窗口函数。

因此,我们可以使用的一种方法是计算每行的所有先前温度值,并将此子查询用作Derived Table,以过滤掉外部SELECT id, RecordDate, temperature, LAG(temperature) OVER (ORDER BY RecordDate) AS prev_temperature FROM weather HAVING temperature > prev_temperature; 查询。

查询#2

Select

View on DB Fiddle