Execução de ordem por cláusula em SQL
Esta questão não é sobre a ordem das execuções. É sobre apenas o ORDER BY.
Na execução padrão é:
DEONDEGRUPO PORTENDOSELECIONARORDENAR PORTOPOEDIT: Esta questão tem sido mais ou menos a questão de "O SQL Server aplica avaliação de curto-circuito ao executar expressões ORDER BY?"A resposta é às vezes! Eu apenas não encontrei uma razão razoável do porquê. Veja Editar # 4.
Agora suponha que eu tenha uma declaração como esta:
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
Esta não é a afirmação real que estou tentando executar, mas apenas um exemplo. Existem três declarações ORDER BY. A terceira declaração é usada apenas para casos raros em que o sobrenome e o primeiro nome coincidem.
Se não houver sobrenomes duplicados, o SQL Server não executa instruções ORDER BY # 2 e # 3? E, logicamente, se não houver sobrenome e nome em duplicado, o SQL Server observa a instrução # 3.
Isso é realmente para otimização. A leitura da tabela de compras deve ser apenas um último recurso. No caso do meu aplicativo, não seria eficiente ler cada "PurchaseDateTime" do agrupamento "Compras" por "CustomerID".
Por favor, mantenha a resposta relacionada à minha pergunta e não uma sugestão como a criação de um índice para CustomerID, PurchaseDateTime em Compras. A verdadeira questão é: o SQL Server ignora instruções ORDER BY desnecessárias?
Edit: Aparentemente, o SQL Server sempre executará todas as instruções, desde que haja uma linha. Mesmo com uma linha, isso resultará em um erro de divisão por zero:
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: Aparentemente, isso não dá divisão por zero:
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
Bem, a resposta original para a minha pergunta é sim, ele executa, mas o que é bom é que eu posso parar de executar com um bom caso quando
Edit 3: Podemos interromper a execução de uma instrução ORDER BY com um CASE QUANDO QUANDO. O truque, eu acho, é descobrir como usá-lo corretamente. CASO QUANDO me dará o que eu quero, que uma execução de curto-circuito em uma instrução ORDER BY. Eu comparei o Plano de Execução no SSMS e, dependendo da instrução CASE WHEN, a tabela de Compras não é escaneada, embora seja uma declaração SELECT / FROM claramente visível:
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
Edit 4: Agora estou completamente confuso. Aqui está um exemplo de @Lieven
WITH Test (name, ID) AS
(SELECT 'Lieven1', 1 UNION ALL SELECT 'Lieven2', 2)
SELECT * FROM Test ORDER BY name, 1/ (ID - ID)
Isso não resulta em divisão por zero, o que significa que o SQL Server faz, de fato, uma avaliação de curto-circuito em algumas tabelas, especificamente aquelas criadas com o comando WITH.
Tentando isso com uma variável 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)
resultará em uma divisão por erro zero.