Этот вопрос не о порядке казни. Речь идет только о ORDER BY.
В стандартном исполнении есть:
РЕДАКТИРОВАТЬ :Этот вопрос был более или менее проблемой " Применяет ли 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.
Это действительно для оптимизации. Чтение из таблицы Purchases должно быть только последним средством. В случае моего приложения было бы неэффективно читать каждое отдельное «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
Редактировать2 :По-видимому, это не дает делить на ноль:
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 WHEN. Хитрость, я думаю, заключается в том, чтобы выяснить, как правильно его использовать. CASE WHEN даст мне то, что я хочу, а именно выполнение короткого замыкания в инструкции ORDER BY. Я сравнил план выполнения в SSMS, и в зависимости от инструкции CASE WHEN таблица Purchases вообще не сканируется, ДАЖЕ ХОТЯ это четко видимая инструкция 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 фактически выполняет оценку короткого замыкания в НЕКОТОРЫХ таблицах, в частности, созданных с помощью команды 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)
приведет к ошибке деления на ноль.