mysql - 使用 MySQL 中的用户定义变量从前一行获取值

标签 mysql sql variables user-defined

我有一个名为“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

Demo

这不仅对 future 的 MySQL 版本可靠。它还适用于许多(所有主要)RDBM 系统。

关于mysql - 使用 MySQL 中的用户定义变量从前一行获取值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54979058/

相关文章:

java - 在 Java 方法性能中使用 final 关键字?

c - 为什么静态变量不允许loop()运行?

mysql - 我怎样才能只选择时间

mysql - 获取论坛上某个类别的最新帖子

java - 使用 hibernate 获取空字符串的 where 子句中的所有值

mysql - 适用于 .MDB 数据库的 SQL 查询不适用于 MySQL 数据库

delphi - 将整数转换为字符串

php - 原始查询 - 更新多列 - 不适用于 Idiorm

MySQL 坚持该字段不存在,然后告诉我它确实存在

php - PHP/SQL语法问题