Этот вопрос не о порядке выполнения. Это примерно как ORDER BY.
В стандартном исполнении:
- С
- WHERE
- GROUP BY
- HAVING
- SELECT
- ЗАКАЗАТЬ
- TOP
РЕДАКТИРОВАТЬ: Этот вопрос был более или менее вопросом: "Применяет ли SQL Server оценку короткого замыкания при выполнении выражений ORDER BY?" Ответ - ИНОГДА! Я просто не нашел разумной причины, почему. См. Редактирование № 4.
Теперь предположим, что у меня есть инструкция вроде этого:
DECLARE @dt18YearsAgo AS DATETIME = DATEADD(YEAR,-18,GETDATE());
SELECT
Customers.Name
FROM
Customers
WHERE
Customers.DateOfBirth > @dt18YearsAgo
ORDER BY
Contacts.LastName ASC, --STATEMENT1
Contacts.FirstName ASC, --STATEMENT2
(
SELECT
MAX(PurchaseDateTime)
FROM
Purchases
WHERE
Purchases.CustomerID = Customers.CustomerID
) DESC --STATEMENT3
Это не настоящий оператор, который я пытаюсь выполнить, а просто пример. Существует три оператора ORDER BY. Третий оператор используется только для редких случаев, когда фамилия и имя совпадают.
Если дубликатов имен не существует, SQL Server не выполняет инструкции ORDER BY # 2 и # 3? И, если логически, если нет дублирующейся фамилии и имени, SQL Server отмечает выполнение оператора # 3.
Это действительно для оптимизации. Чтение из таблицы "Покупки" должно быть только последним. В случае моего приложения было бы нецелесообразно читать каждый "PurchaseDateTime" из группы "Покупки" с помощью "CustomerID".
Пожалуйста, сохраните ответ, связанный с моим вопросом, а не предложение, как создать индекс для CustomerID, PurchaseDateTime в Покупках. Реальный вопрос: SQL Server пропускает ненужные инструкции ORDER BY?
Изменить: По-видимому, SQL Server всегда будет выполнять каждый оператор, если существует одна строка. Даже с одной строкой это даст вам деление на нулевую ошибку:
DECLARE @dt18YearsAgo AS DATETIME = DATEADD(YEAR,-18,GETDATE());
SELECT
Customers.Name
FROM
Customers
WHERE
Customers.DateOfBirth > @dt18YearsAgo
ORDER BY
Contacts.LastName ASC, --STATEMENT1
Contacts.FirstName ASC, --STATEMENT2
1/(Contacts.ContactID - Contacts.ContactID) --STATEMENT3
Edit2: По-видимому, это не дает деления на ноль:
DECLARE @dt18YearsAgo AS DATETIME = DATEADD(YEAR,-18,GETDATE());
SELECT
Customers.Name
FROM
Customers
WHERE
Customers.DateOfBirth > @dt18YearsAgo
ORDER BY
Contacts.LastName ASC, --STATEMENT1
Contacts.FirstName ASC, --STATEMENT2
CASE WHEN 1=0
THEN Contacts.ContactID
ELSE 1/(Contacts.ContactID - Contacts.ContactID)
END --STATEMENT3
Ну, исходный ответ на мой вопрос - ДА, он выполняет, но что приятно, я могу прекратить выполнение с надлежащим CASE WHEN
Изменить 3: Мы можем прекратить выполнение инструкции ORDER BY с надлежащим CASE КОГДА. Хитрость, я думаю, заключается в том, чтобы выяснить, как правильно ее использовать. CASE WHEN даст мне то, что я хочу, что короткое замыкание в инструкции ORDER BY. Я сравнил план выполнения в SSMS и в зависимости от оператора CASE WHEN таблица покупок не отсканирована вообще. ДАЖЕ, ЧТО это отчетливо видный оператор SELECT/FROM:
DECLARE @dt18YearsAgo AS DATETIME = DATEADD(YEAR,-18,GETDATE());
SELECT
Customers.Name
FROM
Customers
WHERE
Customers.DateOfBirth > @dt18YearsAgo
ORDER BY
Contacts.LastName ASC, --STATEMENT1
Contacts.FirstName ASC, --STATEMENT2
CASE WHEN 1=0
THEN
(
SELECT
MAX(PurchaseDateTime)
FROM
Purchases
WHERE
Purchases.CustomerID = Customers.CustomerID
)
ELSE Customers.DateOfBirth
END DESC
Редактировать 4: Теперь я полностью смущен. Вот пример @Lieven
WITH Test (name, ID) AS
(SELECT 'Lieven1', 1 UNION ALL SELECT 'Lieven2', 2)
SELECT * FROM Test ORDER BY name, 1/ (ID - ID)
Это не дает никакого деления на ноль, что означает, что SQL Server действительно делает оценку короткого замыкания в таблицах SOME, особенно тех, которые созданы с помощью команды WITH.
Попробуйте это с помощью переменной TABLE:
DECLARE @Test TABLE
(
NAME nvarchar(30),
ID int
);
INSERT INTO @Test (Name,ID) VALUES('Lieven1',1);
INSERT INTO @Test (Name,ID) VALUES('Lieven2',2);
SELECT * FROM @Test ORDER BY name, 1/ (ID - ID)
приведет к делению на нулевую ошибку.