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.