你能解释一下这种行为吗?
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 |
----------
答案 0 :(得分:3)
符合http://dev.mysql.com/doc/refman/5.0/en/user-variables.html
在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的引用是指选择列表中使用@aa的表达式的别名。这不能按预期工作:@aa包含上一个选定行的id值,而不是当前行。
所以你有前一行的数据。
答案 1 :(得分:2)
我无法解释这种行为(错误?),但这里有一个替代解决方案,可以像你期望的那样工作:
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
答案 2 :(得分:2)
对HAVING
子句的评估导致初始计算@row := @row + 1 AS 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.
答案 3 :(得分:0)
这看起来像bug,但是如果你在C ++中检查增量的实现,你会看到表达式后的postfix ++操作更新变量。对于存储过程,它可以是正确的行为。我认为就是这种情况。