类似的SQL与会话变量产生不同的结果

时间:2018-03-02 23:36:17

标签: mysql sql mariadb

MariaDB 10.1.18

表P(id int AUTO_INCREMENT,rownum int,code int,s int,PRIMARY KEY(id));

select id, rownum, code, s from P order by id;
+----+--------+------+------+
| id | rownum | code | s    |
+----+--------+------+------+
|  1 |      1 |    5 |    1 |
|  2 |      2 |    5 |    1 | 
|  3 |      3 |    5 |    1 |
|  4 |      4 |    5 |    1 |
|  5 |      5 |    5 |    1 |
|  6 |      6 |    7 |    1 |
|  7 |      7 |    7 |    1 |
|  8 |      8 |    7 |    1 |
|  9 |      9 |    7 |    1 |
| 10 |     10 |    7 |    1 |
+----+--------+------+------+

问题:以下2个查询非常相似:第一个查询加入id,第二个加入rownum; id和rownum列具有相同的值(参见上表),但查询结果在计算列N中有所不同:

查询1:加入id列

SELECT P.id, P.rownum, P2.s,
IF(P2.s IS NULL, @val:=@val+1, @val) as N
FROM  P CROSS JOIN (SELECT @val:=0) init
LEFT JOIN P P2
ON (P.id+1=P2.id AND  P.s=1 AND  P2.s=1 AND P.code = P2.code)
ORDER BY P.id;

+----+--------+------+------+
| id | rownum | s    | N    |
+----+--------+------+------+
|  1 |      1 |    1 | 0    |
|  2 |      2 |    1 | 0    |
|  3 |      3 |    1 | 0    |
|  4 |      4 |    1 | 0    |
|  5 |      5 | NULL | 1    |
|  6 |      6 |    1 | 1    |
|  7 |      7 |    1 | 1    |
|  8 |      8 |    1 | 1    |
|  9 |      9 |    1 | 1    |
| 10 |     10 | NULL | 2    |
+----+--------+------+------+

查询2:加入rownum列

SELECT P.id, P.rownum, P2.s,
IF(P2.s IS NULL, @val:=@val+1, @val) as N
FROM  P CROSS JOIN (SELECT @val:=0) init
LEFT JOIN P P2
ON (P.rownum+1=P2.rownum AND  P.s=1 AND  P2.s=1 AND P.code = P2.code)
ORDER BY P.id;

+----+--------+------+------+
| id | rownum | s    | N    |
+----+--------+------+------+
|  1 |      1 |    1 |    0 |
|  2 |      2 |    1 |    0 |
|  3 |      3 |    1 |    0 |
|  4 |      4 |    1 |    0 |
|  5 |      5 | NULL |    1 |
|  6 |      6 |    1 |    0 |
|  7 |      7 |    1 |    0 |
|  8 |      8 |    1 |    0 |
|  9 |      9 |    1 |    0 |
| 10 |     10 | NULL |    2 |
+----+--------+------+------+

1 个答案:

答案 0 :(得分:0)

正如MariaDB knowledge baseMySQL manual中明确记录的那样,除非此语句为SET,否则不应读取用户定义的变量并在同一语句中设置其值。对于其他陈述,它是不安全的,并且结果不能保证,正如您的示例清楚地证明的那样。

附加说明:您在问题中谈论的变量通常被称为“用户定义变量”或“用户变量”,而不是“系统变量”,“全局变量”和“会话”变量',每个变量都意味着系统定义的变量,无论是全部变量还是仅限于给定范围。