SELECT `table_1`.*
FROM `table_1`
INNER JOIN
`table_2` [...]
INNER JOIN
`table_3` [...]
WHERE `table_1`.`id` IN
(
SELECT `id`
FROM [...]
)
AND [more conditions]
Se a tabela interna estiver indexada corretamente, a subconsulta aqui não está sendo "realizada" no sentido estrito da palavra.
Como a subconsulta faz parte de um
IN
expressão, a condição é enviada para a subconsulta e é transformada em um EXISTS
. Na verdade, essa subconsulta é avaliada em cada etapa:
EXISTS
(
SELECT NULL
FROM [...]
WHERE id = table1.id
)
Você pode realmente vê-lo na descrição detalhada fornecida por
EXPLAIN EXTENDED
. É por isso que se chama
DEPENDENT SUBQUERY
:o resultado de cada avaliação depende do valor de table1.id
. A subconsulta como tal não está correlacionada, é a versão otimizada que está correlacionada. MySQL
sempre avalia o EXISTS
cláusula após os filtros mais simples (já que eles são muito mais fáceis de avaliar e há uma probabilidade de que a subconsulta não seja avaliada). Se você quiser que a subconsulta seja avaliada de uma só vez, reescreva a consulta assim:
SELECT table_1.*
FROM (
SELECT DISTINCT id
FROM [...]
) q
JOIN table_1
ON table_1.id = q.id
JOIN table_2
ON [...]
JOIN table_3
ON [...]
WHERE [more conditions]
Isso força a subconsulta a liderar a junção, o que é mais eficiente se a subconsulta for pequena em comparação com
table_1
, e menos eficiente se a subconsulta for grande em comparação com table_1
. Se houver um índice em
[...].id
usado na subconsulta, a subconsulta será realizada usando um INDEX FOR GROUP-BY
.