Якщо ви подивитесь на 2 плани виконання, чи є легка відповідь, який краще? Я цілеспрямовано НЕ створював індекси, тому легше бачити, що відбувається.
Другий план має нижчу оціночну вартість, тому в обмеженому сенсі це "краще".
Наборів даних настільки мало, що оптимізатор не витрачав багато часу на пошук альтернатив. Перша форма запиту буває, щоб знайти план, використовуючи хеш-з'єднання та таблицю котушки на початку. Орієнтовна вартість цього плану настільки низька, що оптимізатор не намагається шукати нічого кращого.
Друга форма запиту буває, щоб знайти план, використовуючи лише вкладені зовнішні петлі, приєднується на початку процесу пошуку, і знову оптимізатор вирішує, що план є досить хорошим. Так трапляється, що цей план оцінюється як дешевший.
При цьому сказано (як зазначено в коментарях до запитання) два запити не є семантично однаковими. Це може бути неважливим для вас, якщо ви можете гарантувати, що результати завжди будуть однаковими для всіх можливих станів вашої бази даних, але оптимізатор не може зробити це припущення. Він лише коли-небудь створює плани, які гарантовано дають однакові результати, визначені SQL, за будь-яких обставин.
Я зрозумів, що вкладений синтаксис також змінює поведінку запиту.
"Вкладений синтаксис" - це лише один аспект усієї специфікації синтаксису приєднання ANSI. Щоб увімкнути повну логічну специфікацію для більш складних шаблонів приєднання, специфікація дозволяє (необов'язково) дужки та FROM
підзапити.
Запит можна записати, використовуючи той самий синтаксис ANSI, використовуючи круглі дужки:
SELECT
A.*,
M.*,
N.*
FROM dbo.Autos AS A
LEFT JOIN
(
dbo.Manufacturers AS N
JOIN dbo.Models AS M
ON M.ManufacturerID = N.ManufacturerID
) ON M.ModelID = A.ModelID;
Ця форма чітко показує, що логічна вимога полягає в тому, щоб залишити приєднання зліва Autos
до результату внутрішнього приєднання Manufacturers
до Models
. Якщо пропустити необов’язкові дужки, ви отримуєте форму, яку ви називаєте "вкладеною":
SELECT
A.*,
M.*,
N.*
FROM dbo.Autos AS A
LEFT JOIN dbo.Manufacturers AS N
JOIN dbo.Models AS M
ON M.ManufacturerID = N.ManufacturerID
ON M.ModelID = A.ModelID;
Це не інший синтаксис - це просто опустити необов’язкові дужки та трохи переформатувати.
Як згадував Мартін, в цьому випадку також можна висловити логічну вимогу за допомогою внутрішніх з'єднань з наступним правильним зовнішнім з'єднанням:
SELECT
A.*,
M.*,
N.*
FROM dbo.Manufacturers AS N
JOIN dbo.Models AS M
ON M.ManufacturerID = N.ManufacturerID
RIGHT JOIN dbo.Autos AS A
ON A.ModelID = M.ModelID;
Усі три форми запитів вище використовують один і той же синтаксис приєднання ANSI. Усі три також складають один і той же план фізичного виконання з наданим набором даних:
Як я вже згадував у своїй відповіді на ваше попереднє запитання, запити, які виражають абсолютно таку ж логічну вимогу, не завжди створюють один і той же план виконання. Яку логічну форму запиту ви хочете використовувати, багато в чому питання стилю. Не існує кореляції між одним конкретним стилем та "кращими" планами запитів взагалі. Як правило, я б радив не переписувати запит, щоб отримати конкретний план, якщо новий запит не є справді логічно ідентичним оригіналу.
Стандарт SQL також дозволяє FROM
запити підрозділів, а ще один спосіб написати ту саму специфікацію запиту:
SELECT *
FROM dbo.Autos AS A
LEFT JOIN
(
SELECT
N.ManufacturerID,
ManufacturerName = N.Name,
M.ModelID,
ModelName = M.Name
FROM dbo.Manufacturers AS N
JOIN dbo.Models AS M
ON M.ManufacturerID = N.ManufacturerID
) AS R1
ON R1.ModelID = A.ModelID;
Використовуючи традиційний синтаксис, ми маємо змінити приєднання на `Виробники на зовнішнє з'єднання, як так ... але це змінює план запитів.
Це, ймовірно, змінює значення запиту, і в цьому випадку це технічно не є вірною альтернативою (але дивіться коментар ypercube до вашого питання).
(Необов’язкові) дужки в синтаксисі приєднання ANSI існують саме для таких складних вимог приєднання, як ця, тому не варто боятися використовувати їх там, де це необхідно.