我有一个名为“t1”的表,我的表是-
+------+------+
| c1 | c2 |
+------+------+
| 1 | 12 |
| 2 | 13 |
| 3 | 14 |
+------+------+
我想获取所有行以及 col2 的先前值。 我使用的查询:-
Select c1,@prev,@prev:=c2 from t1;
我得到以下输出-
+------+---------+------------+
| c1 | @prev | @prev:=c2 |
+------+---------+------------+
| 1 | NULL | 12 |
| 2 | NULL | 13 |
| 3 | NULL | 14 |
+------+---------+------------+
我原本期望在第一行中只得到 NULL。但我在所有行中都得到 NULL。 请解释为什么它在所有行中给出 NULL。
最佳答案
NULL 的原因已记录在 here 中:
Another issue with assigning a value to a variable and reading the value within the same non-SET statement is that the default result type of a variable is based on its type at the start of the statement.
由于@prev
在第一次读取之前没有定义,我们甚至不能说它是什么类型。
现在您可以将其预设为某个值,例如 set @prev = 0;
。但 0
可能是一个有效值,因此您可能希望第一行它为 NULL。 set @prev = null;
都不起作用。但您可以执行以下操作:
set @prev = -1; -- define type as SIGNED
set @prev = null; -- set NULL
现在您的查询应该返回
c1 @prev @prev:=c2
1 null 12
2 12 13
3 13 14
您还可以在单个语句中定义类型并分配 NULL:
set @prev = cast(null as signed);
参见Demo
但是 - 当您在同一语句(SET 除外)中读取和写入用户变量时 - 行为未定义。在文档中,您将找到以下语句:
It is also possible to assign a value to a user variable in statements other than
SET
. (This functionality is deprecated in MySQL 8.0 and subject to removal in a subsequent release.)
...
As a general rule, other than in SET statements, you should never assign a value to a user variable and read the value within the same statement.
...
For other statements, such as
SELECT
, you might get the results you expect, but this is not guaranteed.
我已经用粗体标记了重要部分,因此您可以看到不建议以这种方式使用变量。
较新版本(MySQL 8.0 和 MariaDB 10.2)现在支持window functions like LEAD()
and LAG()
。因此,您可以按以下方式编写查询:
Select c1, c2, lag(c2) over (order by c1) as prev
from t1
这不仅对 future 的 MySQL 版本可靠。它还适用于许多(所有主要)RDBM 系统。
关于mysql - 使用 MySQL 中的用户定义变量从前一行获取值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54979058/