2009-10-08 10 views
1

Когда я использую вычисление или подзапрос в моем предложении ORDER, который уже находится в моем предложении SELECT, знает ли SQL, чтобы просто заказать этот столбец? Или он пересчитывает все для каждой строки при сортировке?Вызывает ли предложение Order By значение в SQL Server?

Например, позволяет сказать, что я пишу страшный запрос, как это:

SELECT EmployeeName, (SELECT COUNT(*) FROM Employee e2 WHERE MgrID = Employee.EmployeeID) 
FROM Employee 
ORDER BY (SELECT COUNT(*) FROM Employee e2 WHERE MgrID = Employee.EmployeeID) 

Да, я знаю, как написать этот запрос лучше, и я знаю, как использовать порядковые в моем заказе по-- но что, если я этого не сделаю? Будет ли SQL перезагружать этот подзапрос для каждой строки или он знает, что он может использовать значение уже в столбце 2?

Как насчет заказа на столбец, который использует функцию?

SELECT EmployeeName, LTRIM(RTRIM(BranchName)) FROM Employee 
ORDER BY LTRIM(RTRIM(BranchName)) 

Выполняет ли это восстановление столбца BranchName для сортировки?

Я рассмотрел некоторые планы выполнения и, похоже, не добавил никаких вычислений, но я думал, что узнаю, что это справедливо как общность вместо моих конкретных случаев.

Основная причина, по которой я спрашиваю, заключается в том, что при выполнении оконной операции, такой как ROWNUMBER() OVER(ORDER BY EmployeeID), я не могу использовать порядковый номер ссылки для ORDER BY. Поэтому, если один из моих столбцов является сложным, я иногда обсуждаю его сброс в переменной таблицы, а затем снова сортирую по нему.

ответ

1

таблица в поле выбора (*) будет сканируется дважды. один раз для заказа и один раз для выбора. вы можете играть больше с помощью использования 100 лучших в обоих подзапросах и т. д., чтобы узнать, что происходит. Означает количество логических чтений, которые производят запросы.

вы можете увидеть его с этим запросом:

SET STATISTICS IO ON 

USE AdventureWorks 
GO 

SELECT (SELECT COUNT(*) FROM Sales.SalesOrderDetail WHERE SalesOrderID = SOH.SalesOrderID) AS c, * 
FROM Sales.SalesOrderHeader SOH 
ORDER by (SELECT COUNT(*) FROM Sales.SalesOrderDetail WHERE SalesOrderID = SOH.SalesOrderID) desc 
GO 

SELECT (SELECT COUNT(*) FROM Sales.SalesOrderDetail WHERE SalesOrderID = SOH.SalesOrderID) AS c, * 
FROM Sales.SalesOrderHeader SOH 
ORDER BY 1 desc 
+0

Да, похоже, что добавляет к нему, но если я именовал поле, ему не нужно повторно сканировать таблицу. MS необходимо добавить поддержку псевдонимов в оконный компонент OVER! – 2009-10-08 17:37:30

1

Он только делает вид, как только двигатель сам может сортировать по имени псевдонима вы даете столбец

SELECT EmployeeName, (SELECT COUNT(*) FROM Employee e2 WHERE MgrID = Employee.EmployeeID) 
FROM Employee 
ORDER BY (SELECT COUNT(*) FROM Employee e2 WHERE MgrID = Employee.EmployeeID) 

также может быть выражено как

SELECT EmployeeName, (SELECT COUNT(*) FROM Employee e2 WHERE MgrID = Employee.EmployeeID) MyField 
FROM Employee 
ORDER BY myField 

Двигатель будет делать в основном то же самое, давая временное имя вашей колонке для использования в предложении order by.

+0

право, но я не получил псевдонимы для работы с OVER() п. Вы не можете сделать что-то вроде SELECT, EmployeeName, (SELECT COUNT (*) FROM e2 Сотрудника WHERE MGRID = Employee.EmployeeID) MyField, ROW_NUMBER() OVER (ORDER BY MyField) в RowNumber ОТ Работника (я должен «Мы выбрали реальную таблицу, на которую все можем ссылаться, но администратор удалил пабы здесь на работе) – 2009-10-08 16:14:28

+0

Псевдонимы в предложении select недоступны в этом предложении select для любого использования. Логически предложение select все сразу. Вы можете использовать CTE или встроенные представления, чтобы назвать это поле, а затем использовать его позже. SELECT EmployeeName, MyField, ROW_NUMBER() OVER (ORDER BY MyField) как rownumber FROM (SELECT EmployeeName, (SELECT COUNT (*) FROM Employee e2 WHERE MgrID = Employee.EmployeeID) MyField FROM Employee) T –