Say I have a query with subqueries in CASE...WHEN...THEN like this (simplified, as the real query I'm working on is little harder on the eyes):
SELECT
CASE
WHEN (subquery1) = 1
THEN (subquery2)
WHEN (subquery1) > 1 AND (subquery3) = 1
THEN (subquery4)
END
FROM foo
All 4 subqueries are dependent subqueries.
Do all 4 subqueries get executed? Cause when I did an EXPLAIN all the subqueries are included in the plan.
Or do only subquery1 get executed first, and if that condition is met, subquery2 will be executed? If not, subquery3 will be executed to examine if the condition is met, and so on... When I re-wrote the query as a stored procedure to only execute the only relevant subqueries this way, there was a performance increase (time reduction). I'm curious to know if the original query was taking more time since it executes all the subqueries, regardless of whether the previous condition have been met.
I tried turn on the general log but the subqueries don't get logged individually. They're logged together as the whole query, so I can't tell which subquery was actually executed. Also tried looking at the MySQL docs on SUBQUERY but I haven't found anything yet.
I find that this is an interesting question.
Explain plans cannot really tell you the answer, since they are static, while condition evaluation occurs at runtime.
The documentation of the case expression does not give details on the order of evaluation of the when conditions. The documentation of the case statement, however, states:
each
WHENclause search_condition expression is evaluated until one is true, at which point its correspondingTHENclause statement_list executes. If no search_condition is equal, theELSEclause statement_list executes, if there is one.
This would tend to indicate that, once a condition is satisfied, further conditions are not checked. But your code contains case expressions, not case statements (which belong to stored procedures).
For what it's worth, here is a (over simplified) test scenario with a case expression. Consider the following code:
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
The first condition evaluates as true. The second condition, if evaluated, would raise runtime error Subquery returns more than 1 row.
When we run the query in this db fiddle, we get the expected result, and no runtime error happens:
| t |
| ---------------- |
| should stop here |
So this also tend to indicate that subqueries are evaluated sequentially, and that MySQL stops evaluating conditions as soon as possible. However, please don't it for granted: in absence of a clear statement in the documentation, this is just empiric!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With