1

当我在我的 SELECT 子句中的 ORDER 子句中使用计算或子查询时,SQL 是否知道只按该列排序?还是在排序时重新计算每一行的所有内容?

例如,假设我正在编写这样一个糟糕的查询:

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

是的,我知道如何更好地编写这个查询,并且我知道如何在我的 order by 中使用序数——但如果我不这样做呢?SQL 会为每一行重新运行这个子查询,还是知道它可以使用第 2 列中已经存在的值?

对使用函数的列进行排序怎么样?

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

它会重新修剪我的 BranchName 列来进行排序吗?

我查看了一些执行计划,它似乎没有添加任何计算,但我想我会发现这是否适用于一般性而不是我的具体情况。

我问的主要原因是在执行窗口操作时,例如ROWNUMBER() OVER(ORDER BY EmployeeID),我不能对ORDER BY. 因此,如果我的某个列很复杂,我有时会争论将其转储到表变量中,然后再对其进行排序。

4

2 回答 2

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 子句中使用。

于 2009-10-08T13:38:28.870 回答
1

select count(*) 中的表将被扫描两次。一次用于订购,一次用于选择。您可以在两个子查询等上使用前 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
于 2009-10-08T14:41:19.053 回答