2014-03-13 43 views
3

当在SQL语句中使用时,会话变量的标准行为是什么。SQL语句中的mysql会话变量值的优先级

案例1
在以下示例中,如所预期会话变量行为。

mysql> set @m1=0, @m2=0, @m3=0; 
Query OK, 0 rows affected (0.00 sec) 

mysql> 
mysql> select 
    -> @m1 := 55 m1, @m2 := 42 m2, @m3 := 66 m3, 
    -> @m1, @m2, @m3, 
    -> @b1 := greatest(@m1, @m2, @m3) b1, 
    -> @b2 := ((@total := @m1 + @m2 + @m3) 
    ->   - (@b1 + least(@m1, @m2, @m3))) b2, 
    -> @total total; 
+----+----+----+------+------+------+------+------+-------+ 
| m1 | m2 | m3 | @m1 | @m2 | @m3 | b1 | b2 | total | 
+----+----+----+------+------+------+------+------+-------+ 
| 55 | 42 | 66 | 55 | 42 | 66 | 66 | 55 | 163 | 
+----+----+----+------+------+------+------+------+-------+ 
1 row in set (0.00 sec) 

mysql> 
mysql> set @m1=0, @m2=0, @m3=0; 
Query OK, 0 rows affected (0.00 sec) 

mysql> select 
    -> @m1 := m1+3, @m2 := m2+3, @m3 := m3+3, 
    -> @m1, @m2, @m3, 
    -> @b1 := greatest(@m1, @m2, @m3) b1, 
    -> @b2 := ((@total := @m1 + @m2 + @m3) 
    ->   - (@b1 + least(@m1, @m2, @m3))) b2, 
    -> @total total 
    -> from 
    -> (select 55 m1, 42 m2, 66 m3 union all select 48, 63, 92) marks_list 
    -> ; 
+-------------+-------------+-------------+------+------+------+------+------+-------+ 
| @m1 := m1+3 | @m2 := m2+3 | @m3 := m3+3 | @m1 | @m2 | @m3 | b1 | b2 | total | 
+-------------+-------------+-------------+------+------+------+------+------+-------+ 
|   58 |   45 |   69 | 58 | 45 | 69 | 69 | 58 | 172 | 
|   51 |   66 |   95 | 51 | 66 | 95 | 95 | 66 | 212 | 
+-------------+-------------+-------------+------+------+------+------+------+-------+ 
2 rows in set (0.00 sec) 

上面的例子没有使用任何聚合函数。

案例2
当类似的声明用聚合函数像countsumgroup by执行,结果模式是完全不同的。

请给出一个例子:SQL Fiddle

发布此查询之前,我试着去了解SQL-Query-Order-of-Operations

回答

1

如果我理解正确,您在询问select语句中表达式的评估顺序。 MySQL的documentation是很清楚,你不能依靠这一点:

在下面的语句,你 可能会认为MySQL将评估@a第一,然后做一个 分配第二:

SELECT @a, @a:[email protected]+1, ...; 

然而,涉及用户 变量的表达式的评估顺序未定义。

我认为问题在于您的期望值是按顺序分配的。这是不正确的。也就是说,我必须承认,当使用变量时,我会时不时地做出相同的连续性评估假设,主要是因为懒惰以及它通常工作的事实。

如果你想保证连续评估,然后使用case招:

select (case when (@m := 55) is null then null 
      when (@m := 42) is null then null 
     . . . 
     end) 

的条件case保证顺序计算,直到有一个为真。与null比较确保所有评估。

+0

+1。不涉及汇总时,执行顺序非常简单。通过分组,行为显然是令人困惑和不确定的。 –