mysql之CASE..WHEN 中的所有子查询是否都被执行,即使只满足一个条件

不点 阅读:99 2024-12-31 21:38:35 评论:0

假设我在 CASE...WHEN...THEN 中有一个带有子查询的查询,就像这样(经过简化,因为我正在处理的实际查询看起来有点困难):

SELECT 
  CASE  
    WHEN (subquery1) = 1 
      THEN (subquery2) 
    WHEN (subquery1) > 1 AND (subquery3) = 1 
      THEN (subquery4) 
  END 
FROM foo 

所有 4 个子查询都是依赖子查询。

是否所有 4 个子查询都被执行了?因为当我执行 EXPLAIN 时,所有子查询都包含在计划中。

或者只先执行subquery1,满足条件再执行subquery2?如果没有,将执行 subquery3 以检查是否满足条件,依此类推......当我将查询重新编写为存储过程以仅以这种方式执行唯一相关的子查询时,性能提高(时间减少).我很想知道原始查询是否花费了更多时间,因为它执行了所有子查询,无论是否满足先前的条件。

我尝试打开通用日志,但子查询没有单独记录。它们作为整个查询记录在一起,所以我无法判断实际执行了哪个子查询。还尝试查看 SUBQUERY 上的 MySQL 文档,但我还没有找到任何内容。

请您参考如下方法:

我发现这是一个有趣的问题。

解释计划并不能真正告诉您答案,因为它们是静态的,而条件评估发生在运行时。

case expression 的文档没有详细说明 when 条件的评估顺序。 case statement 的文档, 然而, 状态:

each WHEN clause search_condition expression is evaluated until one is true, at which point its corresponding THEN clause statement_list executes. If no search_condition is equal, the ELSE clause statement_list executes, if there is one.

这往往表明,一旦满足一个条件,就不再检查进一步的条件。但是您的代码包含 case 表达式,而不是 case 语句(属于存储过程)。

对于它的值(value),这里有一个(过度简化的)测试场景,带有一个 case 表达式。考虑以下代码:

select case  
    when (select 1) = 1 then 'should stop here' 
    when (select 1 union all select 2) = 1 then 'should not get there, or it will die' 
end t 

第一个条件评估为真。如果评估第二个条件,将引发运行时错误 Subquery returns more than 1 row

当我们在 this db fiddle 中运行查询时,我们得到了预期的结果,并且没有发生运行时错误:

| t                | 
| ---------------- | 
| should stop here | 

所以这也往往表明子查询是按顺序求值的,MySQL会尽快停止求值条件。但是,请不要想当然:在文档中没有明确说明的情况下,这只是经验!


标签:mysql
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号