Mysql 你能解释一下这种行为吗?

Mysql 你能解释一下这种行为吗?,mysql,Mysql,你能解释一下这种行为吗 CREATE TABLE test( a INT ); INSERT INTO test VALUES (21), (22), (23), (24), (25); SELECT @row := @row + 1 AS r, a FROM test JOIN ( SELECT @row := 0 ) AS init ORDER BY a; ---------- | r | a | ---------- | 1 | 21 | | 2 | 22 | | 3 |

你能解释一下这种行为吗

CREATE TABLE test( a INT );

INSERT INTO test VALUES (21), (22), (23), (24), (25);

SELECT @row := @row + 1 AS r, a FROM test
  JOIN ( SELECT @row := 0 ) AS init
  ORDER BY a;

----------
| r | a  |
----------
| 1 | 21 |
| 2 | 22 |
| 3 | 23 |
| 4 | 24 |
| 5 | 25 |
----------

SELECT @row := @row + 1 AS r, a FROM test
  JOIN ( SELECT @row := 0 ) AS init
  HAVING r = 3
  ORDER BY a;

----------
| r | a  |
----------
| 4 | 23 |
----------

我无法解释这种行为(bug?),但这里有一个替代解决方案,它的工作方式与您预期的工作方式类似:

SELECT * FROM
    (SELECT @row := @row + 1 AS r, a FROM test
      JOIN ( SELECT @row := 0 ) AS init
      ORDER BY a) as tmp
WHERE tmp.r = 3

HAVING
子句的求值导致将
@row:=@row+1初始计算为r

1st Pass: r = 1, fail.
2nd Pass: r = 2, fail.
3rd Pass: r = 3, success.
然后,当将结果发送到客户端时,
@row:=@row+1 AS r
将再次求值,@row的值变为4,这样您就得到了结果:

r = 4, a = 23.
依照

在SELECT语句中,仅当将每个SELECT表达式发送到客户端时,才会对其求值。这意味着,在HAVING、GROUP BY或ORDER BY子句中,引用在select表达式列表中指定值的变量不会按预期工作:

mysql> SELECT (@aa:=id) AS a, (@aa+3) AS b FROM tbl_name HAVING b=5;
HAVING子句中对b的引用引用了select列表中使用@aa的表达式的别名。这不符合预期:@aa包含上一个选定行的id值,而不是当前行的id值


所以你有前一行的数据。

< P>这看起来像Bug,但是如果你检查C++中的增量的执行,你会看到表达式后的后缀+操作更新变量。对于存储过程,它可以是正确的行为。我想是这样的。

这意味着select中的表达式要计算两次?在这种情况下,必须这样做,因为计算r来查找联接查询,然后在选择时将其添加到。我在任何查询中都没有看到任何
r+1
r
@row:=@row+1
的别名。此外,
@row+1
正是每行基于1的行号,请参见第一个查询及其结果。@在比较之前,没有人使用HAVING子句再次计算
r
的表达式。确实如此。我在脑海中看到它,它循环通过,r=1,不,r=2,不,r=3,太好了,我们满足了having子句。现在选择值,确定将1添加到r(@row)并返回,r=4,a=23。这是我的第二次尝试,因为它用于GROUP BY,可能会导致额外的计算。我已经意识到这一点,使用此替代方法来回答。情况几乎相同:
从r>0.5的值中选择rand()r。您将无法获得预期的结果。HAVING子句再次进行计算。但MySQL为什么这么做很有趣。这似乎不适用于
orderby
子句。但我认为这是最好的答案+1.