First, this depends on the version of MySQL. I believe that version 5.6 optimizes such queries correctly. MySQL documentation is inconsistent on this. For instance, here it says one thing:
Consider the following subquery comparison:
outer_expr IN (SELECT inner_expr FROM ... WHERE subquery_where)
MySQL evaluates queries “from outside to inside.” That is, it first
obtains the value of the outer expression outer_expr, and then runs
the subquery and captures the rows that it produces.
This "from outside to inside" means that the subquery is evaluated for each row. This is consistent with my experience with MySQL.
The documentation suggests otherwise here:
Some optimizations that MySQL itself makes are:
- MySQL executes uncorrelated subqueries only once. Use EXPLAIN to make sure that a given subquery really is uncorrelated.
- MySQL rewrites IN, ALL, ANY, and SOME subqueries in an attempt to take advantage of the possibility that the select-list columns in the subquery are indexed.
I believe the statement does not refer to in
clauses. Perhaps what happens is that the subquery is rewritten as a correlated subquery to check for indexes, and then it is run multiple times (regardless of the presence of a index).
LEFT JOIN
isn't the same thing.INNER JOIN
is the answer. – Migratory