【问题标题】:Precedence of a mysql session variable value in an sql statementsql语句中mysql会话变量值的优先级
【发布时间】:2014-04-18 18:22:25
【问题描述】:

在 SQL 语句中使用会话变量时的标准行为是什么。

案例 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

【问题讨论】:

    标签: mysql aggregate-functions operator-precedence mysql-variables


    【解决方案1】:

    如果我理解正确,您是在询问select 语句中表达式的求值顺序。 MySQL documentation 很清楚你不能依赖这个:

    在以下声明中,您 可能会认为 MySQL 会先评估 @a 然后执行 作业二:

    SELECT @a, @a:=@a+1, ...;
    

    但是,涉及用户的表达式的计算顺序 变量未定义。

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

    如果您想保证顺序评估,请使用case 技巧:

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

    case 保证条件的顺序评估,直到条件为真。与null 的比较确保所有都得到评估。

    【讨论】:

    • +1。当不涉及聚合时,执行顺序非常简单。使用分组,行为肯定是令人困惑和不确定的。
    猜你喜欢
    • 2013-08-03
    • 2020-12-20
    • 2012-02-19
    • 2020-10-09
    • 2013-06-03
    • 2016-01-05
    • 2012-07-11
    • 1970-01-01
    • 2018-02-22
    相关资源
    最近更新 更多