如何在 MySQL 中滞后列?

Posted

技术标签:

【中文标题】如何在 MySQL 中滞后列?【英文标题】:How do I lag columns in MySQL? 【发布时间】:2011-07-25 21:28:55 【问题描述】:

考虑下表:

SELECT id, value FROM table ORDER BY id ASC;
+-----+---------+
| id  | value   |
+-----+---------+
| 12  | 158     |
| 15  | 346     |
| 27  | 334     |
| 84  | 378     |
| 85  | 546     |
+-----+---------+

id 列是自动递增的,但包含间隙。 value 列是数字。

我想通过设置value 相对于上面两行的value 来查看value 随着时间的增加。那是行id=85 我想设置行id=85 (546) 的value 与行id=27 (334) 的value 相关。因此,要为行 id=85 计算的值是 546/334=1.63473。

这是我想要达到的结果:

SELECT id, value, ...;
+-----+---------+---------------------+
| id  | value   | value/lag(value, 2) | (the syntax value/lag(value, 2) is made up)
+-----+---------+---------------------+
| 12  | 158     | NULL                |
| 15  | 346     | NULL                |
| 27  | 334     | 2.11392             | (334/158=2.11392)
| 84  | 378     | 1.09248             | (378/346=1.09248)
| 85  | 546     | 1.63473             | (546/334=1.63473)
+-----+---------+---------------------+

如何在 mysql 中执行这种滞后?

请注意,id 列包含间隙,因此仅使用 t1.id = t2.id - 2 加入同一个表是行不通的。

【问题讨论】:

SQL 标准中有一个 lag() 函数,但是 MySQL 不支持这个。 【参考方案1】:

由于当前行和要从中获取“历史”数据的行之间只有两行,您是否可以使用变量来临时存储数据,例如:

set @oldid0=999999; set @oldid1=999999; set @oldid2=999999; select @oldid0:=@oldid1,@oldid1:=@oldid2,@oldid2:=id, value/@oldid0 from table order by id asc;

这是一个非常不整洁的解决方案,但我认为它会完成这项工作。也许有一些方法可以防止显示变量,我还没有研究那么远。

【讨论】:

Lag(2) 只是一个例子。我正在寻找一个允许说 Lag(365) 的通用解决方案:-) 啊,我看了你的问题并愚蠢地认为你的意思只是滞后(2)【参考方案2】:

这是一个在 MySQL 中返回你想要的内容的解决方案

SET @a :=0;
SET @b :=2;
SELECT r.id, r.value, r.value/r2.value AS 'lag'
FROM
(SELECT if(@a, @a:=@a+1, @a:=1) as rownum, id, value FROM results) AS r
LEFT JOIN
(SELECT if(@b, @b:=@b+1, @b:=1) as rownum, id, value FROM results) AS r2
ON r.rownum = r2.rownum

MySQL 5.1 不喜欢针对子查询的自联接,因此您必须对行进行两次计数,因此不像它可能的那样整洁或可扩展,但它确实使指定延迟变得简单。

对于使用 Oracle 的读者来说,这更容易

SELECT id, value, value/lag(value, 2) over (order by id) as lag from results;

【讨论】:

对于使用 Oracle 的读者:或 PostgreSQL 或 DB2 或 Teradata :)

以上是关于如何在 MySQL 中滞后列?的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 加入日期列存在 1 个月的滞后和性能问题

如何将此 postgresql 滞后语句移植到 mysql?

使用滞后访问mysql中的前一行值

如何在 MongoDB 中执行领先和滞后

在 MySQL 中模拟滞后函数

如何在 Python Pandas 回归模型中使用滞后时间序列变量?