Eu tenho uma subconsulta correlacionada como esta (de BOL ):
SELECT DISTINCT c.LastName, c.FirstName, e.BusinessEntityID
FROM Person.Person AS c JOIN HumanResources.Employee AS e
ON e.BusinessEntityID = c.BusinessEntityID
WHERE 5000.00 IN
(SELECT Bonus
FROM Sales.SalesPerson sp
WHERE e.BusinessEntityID = sp.BusinessEntityID) ;
GO
Quando reescrevo esta consulta usando junções
select c.LastName, c.FirstName, e.BusinessEntityID, d.Bonus
from Person.Person as c
inner join HumanResources.Employee as e on e.BusinessEntityID = c.BusinessEntityID
inner join Sales.SalesPerson as d on d.BusinessEntityID = c.BusinessEntityID
where Bonus = 5000.00
E veja o plano de execução real, parece exatamente o mesmo em ambas as consultas. Por quê? Eu estava pensando que a subconsulta correlacionada é muito mais lenta por causa do loop aninhado e o plano de execução parece diferente? É porque não há muitos dados nessas tabelas?
As duas consultas são logicamente idênticas e produzem o mesmo plano. A fase de simplificação do Query Optimizer lida com isso.
Eles são idênticos por causa das restrições que estão nas tabelas - chaves estrangeiras, unicidade, nulidade...
Um bom otimizador reconhecerá quando uma consulta correlacionada pode ter sido escrita como uma junção e usará o mesmo plano. Muitas consultas correlacionadas podem ser facilmente escritas como uma junção. Nesse caso, o otimizador está fazendo seu trabalho. A otimização da consulta dessa maneira permite planos que não fariam sentido usando a consulta correlacionada.
Costumo escrever uma consulta correlacionada quando faz sentido semanticamente e usar uma junção quando for apropriado semanticamente. Otimizadores modernos irão gerar a consulta apropriada. À medida que os otimizadores melhoram, eu escrevo consultas para facilitar o entendimento e não tentar adivinhar o otimizador. (Acho que o otimizador geralmente se sai melhor do que eu. Há casos raros em que sei algo que o otimizador não pode determinar a partir da consulta.)