SELECT - ORDER BY 子句 (Transact-SQL)
適用於:sql Server Azure SQL 資料庫 Azure SQL 受控執行個體 Azure Synapse Analytics Platform System (PDW) SQL 分析端點Microsoft網狀架構倉儲中的 Microsoft Fabric SQL 資料庫Microsoft網狀架構
排序 SQL Server 中查詢所傳回的資料。 此子句可用於:
依據指定的資料行清單排序查詢的結果集,並選擇性地將傳回的資料列限制在指定範圍內。 除非指定 子句,否則
ORDER BY
不會保證在結果集中傳回數據列的順序。決定次序函數值套用至結果集的順序。
注意
ORDER BY
Azure Synapse Analytics 或 Analytics Platform System (PDW) 中的 或 (CTAS) 語句不支援 SELECT
INTO
/。CREATE TABLE AS SELECT
語法
SQL Server 和 Azure SQL Database 的語法。
ORDER BY order_by_expression
[ COLLATE collation_name ]
[ ASC | DESC ]
[ , ...n ]
[ <offset_fetch> ]
<offset_fetch> ::=
{
OFFSET { integer_constant | offset_row_count_expression } { ROW | ROWS }
[
FETCH { FIRST | NEXT } { integer_constant | fetch_row_count_expression } { ROW | ROWS } ONLY
]
}
Azure Synapse Analytics 和平行處理數據倉儲的語法。
[ ORDER BY
{
order_by_expression
[ ASC | DESC ]
} [ , ...n ]
]
引數
order_by_expression
指定要排序查詢結果集的資料行或運算式。 排序數據行可以指定為名稱或數據行別名,或是代表選取清單中數據行位置的非負整數。
您可以指定多個排序資料行。 資料行名稱必須是唯一名稱。 子句中 ORDER BY
排序數據行的順序會定義排序結果集的組織。 也就是說,結果集依據第一個資料行來排序,然後該排序的清單依據第二個資料行來排序,依此類推。
子句中 ORDER BY
參考的數據行名稱必須對應至選取清單中的數據行或數據行別名,或是子句中所 FROM
指定數據表中所定義的數據行,且沒有任何模棱兩可。 ORDER BY
如果 子句從選取清單中參考數據行別名,則必須自行使用數據行別名,而不是子句中ORDER BY
某些表達式的一部分,例如:
SELECT SCHEMA_NAME(schema_id) AS SchemaName
FROM sys.objects
ORDER BY SchemaName; -- correct
SELECT SCHEMA_NAME(schema_id) AS SchemaName
FROM sys.objects
ORDER BY SchemaName + ''; -- wrong
COLLATE collation_name
指定ORDER BY
作業應該根據collation_name中指定的定序執行,而不是根據數據表或檢視中所定義之數據行的定序來執行。 collation_name可以是 Windows 定序名稱或 SQL 定序名稱。 如需詳細資訊,請參閱定序和 Unicode 支援。 COLLATE
僅適用於 char、varchar、nchar 和 nvarchar 類型的數據行。
ASC | DESC
指定指定之資料行的值應該以遞增或遞減順序排序。 ASC
從最低值到最高值進行排序。 DESC
從最高值到最低值進行排序。 ASC
為預設的排序順序。 NULL
值會被視為最低的可能值。
OFFSET { integer_constant | offset_row_count_expression } { ROW | ROWS }
適用於:SQL Server 2012 (11.x) 和更新版本、Azure SQL 資料庫 和 Azure SQL 受控執行個體。
指定要略過的資料列數目,然後才開始從查詢運算式傳回資料列。 值可以是大於或等於零的整數常數或運算式。
offset_row_count_expression 可以是變數、參數或常數純量子查詢。 使用子查詢時,它無法參考外部查詢範圍中定義的任何數據行。 也就是說,它無法與外部查詢相互關聯。
ROW
和 ROWS
是同義字,並提供 ANSI 相容性。
在查詢執行計劃中,位移數據列計數值會顯示在查詢運算子的 TOP
Offset 屬性中。
FETCH { FIRST | NEXT } { integer_constant | fetch_row_count_expression } { ROW | ROWS } ONLY
適用於:SQL Server 2012 (11.x) 和更新版本、Azure SQL 資料庫 和 Azure SQL 受控執行個體。
指定要在 OFFSET
處理 子句之後傳回的數據列數目。 值可以是大於或等於一的整數常數或運算式。
fetch_row_count_expression 可以是變數、參數或常數純量子查詢。 使用子查詢時,它無法參考外部查詢範圍中定義的任何數據行。 也就是說,它無法與外部查詢相互關聯。
FIRST
和 NEXT
是同義字,並提供 ANSI 相容性。
ROW
和 ROWS
是同義字,並提供 ANSI 相容性。
在查詢執行計劃中,位移數據列計數值會顯示在查詢運算子的 TOP
Rows 或 Top 屬性中。
最佳作法
請避免將 子句中的 ORDER BY
整數指定為選取清單中數據行的位置表示法。 例如,雖然 之類的 SELECT ProductID, Name FROM Production.Production ORDER BY 2
語句有效,但相較於指定實際數據行名稱,其他語句並不容易理解。 此外,選取清單的變更,例如變更數據行順序或新增數據行,需要修改 ORDER BY
子句,以避免非預期的結果。
在語句中 SELECT TOP (<n>)
,一律使用 ORDER BY
子句。 這是可預測地指出哪些數據列受到 TOP
影響的唯一方法。 如需詳細資訊,請參閱 TOP。
互通性
搭配 SELECT...INTO
或 INSERT...SELECT
語句使用 來插入來自另一個來源的數據列時, ORDER BY
子句不保證數據列會以指定的順序插入。
在 OFFSET
檢視中使用 和 FETCH
並不會變更檢視的可更新性屬性。
限制
子句中的數據 ORDER BY
行數目沒有限制。 不過,子句中指定的 ORDER BY
數據行大小總計不能超過8,060個字節。
類型為 ntext、text、image、geography、geometry 和 xml 的數據行不能用於 子句中ORDER BY
。
當排名函式中出現order_by_expression時,無法指定整數或常數。 如需詳細資訊,請參閱 SELECT - OVER 子句。
如果數據表名稱在 子句中 FROM
為別名,則只能使用別名名稱來限定子句中的數據 ORDER BY
行。
如果SELECT
語句包含下列其中一個子句或運算子,則必須在選取清單中定義 子句中指定的ORDER BY
資料行名稱和別名:
UNION
算子EXCEPT
算子INTERSECT
算子SELECT DISTINCT
此外,當語句包含 、 EXCEPT
或 INTERSECT
運算子時,必須在第一個 UNION
(左側) 查詢的選取清單中指定資料行名稱或數據行別名。
在使用 UNION
、 EXCEPT
或 INTERSECT
運算子的查詢中, ORDER BY
只允許在 語句結尾。 只有在您在最上層查詢中指定 UNION
、 EXCEPT
和 INTERSECT
,而不是在子查詢中時,才會套用此限制。 請參閱後續的<範例>一節。
子 ORDER BY
句在檢視、內嵌函式、衍生數據表和子查詢中無效,除非 TOP
同時指定 或 OFFSET
和 FETCH
子句。 當ORDER BY
用於這些物件時,子句只會用來判斷 子句或 OFFSET
和 FETCH
子句所TOP
傳回的數據列。 ORDER BY
子句不保證查詢這些建構時的已排序結果,除非ORDER BY
查詢本身也指定。
OFFSET
和 FETCH
不支援在索引檢視表或使用 子句定義的檢視中 CHECK OPTION
。
OFFSET
和 FETCH
可用於允許 TOP
且 ORDER BY
具有下列限制的任何查詢:
子
OVER
句不支援OFFSET
和FETCH
。OFFSET
和FETCH
不能直接在 、UPDATE
、MERGE
和DELETE
語句中INSERT
指定,但可以在這些語句中定義的子查詢中指定。 例如,在語句中INSERT INTO SELECT
,OFFSET
可以在語句中SELECT
指定 和FETCH
。在使用、
EXCEPT
或運算子的查詢UNION
中,FETCH
OFFSET
只能在指定查詢結果順序的最終查詢中INTERSECT
指定。TOP
無法在相同的查詢表達式中與OFFSET
和FETCH
結合(在相同的查詢範圍中)。
使用 OFFSET 和 FETCH 來限制傳回的數據列
您應該使用 OFFSET
和 FETCH
子句,而不是 TOP
子句來實作查詢分頁解決方案,並限制傳送至用戶端應用程式的數據列數目。
使用 OFFSET
和 FETCH
作為分頁解決方案需要針對傳回至用戶端應用程式的每個 數據頁面 執行一次查詢。 例如,若要以 10 個數據列遞增傳回查詢的結果,您必須一次執行查詢,以傳回數據列 1 到 10,然後再次執行查詢以傳回數據列 11 到 20,依此等。 每個查詢各自獨立,無論如何都不相關。 這表示,不同於使用資料指標執行查詢一次,並在伺服器上維護狀態,用戶端應用程式會負責追蹤狀態。 若要使用 OFFSET
和 FETCH
達到查詢要求之間的穩定結果,必須符合下列條件:
查詢所使用的基礎資料不可以變更。 也就是說,查詢所觸及的數據列不會更新,或是查詢中頁面的所有要求都會使用快照集或可串行化的交易隔離,在單一交易中執行。 如需這些交易隔離等級的詳細資訊,請參閱 SET TRANSACTION ISOLATION LEVEL。
子
ORDER BY
句包含保證是唯一的數據行或數據行組合。
請參閱本文稍後的一節中的範例。
如果您的分頁解決方案中一致執行計劃很重要,請考慮使用 和 FETCH
參數的OPTIMIZE FOR
OFFSET
查詢提示。 請參閱本文稍後的<範例>一節中的指定 OFFSET 和 FETCH 值的表達式。 如需 的詳細資訊 OPTIMIZE FOR
,請參閱 查詢提示。
範例
本文 Transact-SQL 程式碼範例使用 AdventureWorks2022
或 AdventureWorksDW2022
範例資料庫,從 Microsoft SQL Server Samples 和 Community Projects (Microsoft SQL Server 範例和社群專案)首頁即可下載。
類別 | 代表性語法元素 |
---|---|
基本語法 | ORDER BY |
指定遞增和遞減順序 | DESC 或 ASC |
指定定序 | COLLATE |
指定條件式順序 | CASE 運算式 |
在排名函式中使用 ORDER BY | 次序函數 |
限制傳回的數據列數目 | OFFSET 和 FETCH |
搭配 UNION、EXCEPT 和 INTERSECT 使用 ORDER BY | UNION |
基本語法
本節中的範例示範使用最低必要語法的 ORDER BY
子句基本功能。
A. 指定選取清單中定義的單一資料行
下列範例會依據數值 ProductID
資料行來排序結果集。 因為未指定特定的排序順序,因此會使用預設的 (遞增順序)。
USE AdventureWorks2022;
GO
SELECT ProductID, Name
FROM Production.Product
WHERE Name LIKE 'Lock Washer%'
ORDER BY ProductID;
B. 指定未在選取清單中定義的數據行
下列範例會依未包含在選取清單中的數據行排序結果集,但定義於 子句中指定的 FROM
數據表中。
USE AdventureWorks2022;
GO
SELECT ProductID, Name, Color
FROM Production.Product
ORDER BY ListPrice;
C. 將別名指定為排序數據行
下列範例會指定資料行別名 SchemaName
做為排序次序資料行。
USE AdventureWorks2022;
GO
SELECT name, SCHEMA_NAME(schema_id) AS SchemaName
FROM sys.objects
WHERE type = 'U'
ORDER BY SchemaName;
D. 將表達式指定為排序數據行
下列範例會使用運算式做為排序資料行。 表達式的定義方式是使用 DATEPART
函式來排序員工雇用年份的結果集。
USE AdventureWorks2022;
GO
SELECT BusinessEntityID, JobTitle, HireDate
FROM HumanResources.Employee
ORDER BY DATEPART(year, HireDate);
指定遞增和遞減排序順序
A. 指定遞減順序
下列範例會依據數值資料行 ProductID
以遞減順序來排序結果集。
USE AdventureWorks2022;
GO
SELECT ProductID, Name
FROM Production.Product
WHERE Name LIKE 'Lock Washer%'
ORDER BY ProductID DESC;
B. 指定遞增順序
下列範例會依據資料行 Name
以遞增順序來排序結果集。 字元會以字母順序排序,而不是以數值順序排序。 也就是說,10 會排序在 2 之前。
USE AdventureWorks2022;
GO
SELECT ProductID, Name
FROM Production.Product
WHERE Name LIKE 'Lock Washer%'
ORDER BY Name ASC;
C. 同時指定遞增和遞減順序
下列範例會依據兩個資料行來排序結果集。 查詢的結果集會先依據 FirstName
資料行以遞增順序排序,然後再依據 LastName
資料行以遞減順序排序。
USE AdventureWorks2022;
GO
SELECT LastName, FirstName
FROM Person.Person
WHERE LastName LIKE 'R%'
ORDER BY FirstName ASC, LastName DESC;
指定定序
下列範例示範如何在 子句中 ORDER BY
指定定序,以變更傳回查詢結果的順序。 建立的資料表中包含一個資料行,這個資料行是透過使用不區分大小寫、不區分腔調字的定序來定義。 值會插入各種大小寫和強調差異。 由於 子句中 ORDER BY
未指定定序,因此第一個查詢會在排序值時使用數據行的定序。 在第二個查詢中,子句中 ORDER BY
會指定區分大小寫、區分腔調字的定序,這會變更傳回數據列的順序。
USE tempdb;
GO
CREATE TABLE #t1 (name NVARCHAR(15) COLLATE Latin1_General_CI_AI);
GO
INSERT INTO #t1
VALUES (N'Sánchez'),
(N'Sanchez'),
(N'sánchez'),
(N'sanchez');
-- This query uses the collation specified for the column 'name' for sorting.
SELECT name
FROM #t1
ORDER BY name;
-- This query uses the collation specified in the ORDER BY clause for sorting.
SELECT name
FROM #t1
ORDER BY name COLLATE Latin1_General_CS_AS;
指定條件式順序
下列範例會 CASE
使用 子句中的 ORDER BY
表達式,根據指定的數據行值,有條件地判斷數據列的排序順序。 在第一則範例中,系統會評估 SalariedFlag
資料表之 HumanResources.Employee
資料行的值。 將 SalariedFlag
設定為 1 的員工會以 BusinessEntityID
的遞減順序傳回。 將 SalariedFlag
設定為 0 的員工會以 BusinessEntityID
的遞增順序傳回。 在第二則範例中,結果集會依照資料行 TerritoryName
排序 (當資料行 CountryRegionName
等於 'United States' 時) 以及依照 CountryRegionName
排序 (針對所有其他資料列)。
SELECT BusinessEntityID,
SalariedFlag
FROM HumanResources.Employee
ORDER BY
CASE SalariedFlag
WHEN 1 THEN BusinessEntityID
END DESC,
CASE
WHEN SalariedFlag = 0 THEN BusinessEntityID
END;
GO
SELECT BusinessEntityID,
LastName,
TerritoryName,
CountryRegionName
FROM Sales.vSalesPerson
WHERE TerritoryName IS NOT NULL
ORDER BY
CASE CountryRegionName
WHEN 'United States' THEN TerritoryName
ELSE CountryRegionName
END;
在排名函式中使用 ORDER BY
下列範例使用ORDER BY
排名函式ROW_NUMBER
、 RANK
DENSE_RANK
、 和NTILE
中的 子句。
USE AdventureWorks2022;
GO
SELECT p.FirstName,
p.LastName,
ROW_NUMBER() OVER (ORDER BY a.PostalCode) AS "Row Number",
RANK() OVER (ORDER BY a.PostalCode) AS "Rank",
DENSE_RANK() OVER (ORDER BY a.PostalCode) AS "Dense Rank",
NTILE(4) OVER (ORDER BY a.PostalCode) AS "Quartile",
s.SalesYTD,
a.PostalCode
FROM Sales.SalesPerson AS s
INNER JOIN Person.Person AS p
ON s.BusinessEntityID = p.BusinessEntityID
INNER JOIN Person.Address AS a
ON a.AddressID = p.BusinessEntityID
WHERE TerritoryID IS NOT NULL
AND SalesYTD <> 0;
限制傳回的數據列數目
適用於:SQL Server 2012 (11.x) 和更新版本、Azure SQL 資料庫 和 Azure SQL 受控執行個體。
下列範例會使用 OFFSET
和 FETCH
來限制查詢所傳回的數據列數目。
A. 指定 OFFSET 和 FETCH 值的整數常數
下列範例會將整數常數指定為 和 FETCH
子句的值OFFSET
。 第一個查詢傳回依資料行 DepartmentID
排序的所有資料列。 比較這個查詢所傳回的結果與後面兩個查詢的結果。 下一個查詢會使用 子句 OFFSET 5 ROWS
略過前五個數據列,並傳回所有剩餘的數據列。 最後查詢使用子句 OFFSET 0 ROWS
從第一個資料列開始,然後再使用 FETCH NEXT 10 ROWS ONLY
,將傳回的資料列限制在已排序結果集內的 10 個資料列。
USE AdventureWorks2022;
GO
-- Return all rows sorted by the column DepartmentID.
SELECT DepartmentID, Name, GroupName
FROM HumanResources.Department
ORDER BY DepartmentID;
-- Skip the first 5 rows from the sorted result set and return all remaining rows.
SELECT DepartmentID, Name, GroupName
FROM HumanResources.Department
ORDER BY DepartmentID OFFSET 5 ROWS;
-- Skip 0 rows and return only the first 10 rows from the sorted result set.
SELECT DepartmentID, Name, GroupName
FROM HumanResources.Department
ORDER BY DepartmentID OFFSET 0 ROWS
FETCH NEXT 10 ROWS ONLY;
B. 指定 OFFSET 和 FETCH 值的變數
下列範例會宣告 變數@RowsToSkip
和 ,並在和 @FetchRows
FETCH
子句中OFFSET
指定這些變數。
USE AdventureWorks2022;
GO
-- Specifying variables for OFFSET and FETCH values
DECLARE
@RowsToSkip TINYINT = 2,
@FetchRows TINYINT = 8;
SELECT DepartmentID, Name, GroupName
FROM HumanResources.Department
ORDER BY DepartmentID ASC OFFSET @RowsToSkip ROWS
FETCH NEXT @FetchRows ROWS ONLY;
C. 指定 OFFSET 和 FETCH 值的運算式
下列範例會使用 表達式 @StartingRowNumber - 1
來指定 OFFSET
值和表達式 @EndingRowNumber - @StartingRowNumber + 1
來指定 FETCH 值。 此外,已指定查詢提示 OPTIMIZE FOR
。 在查詢進行編譯和最佳化時,此提示可用來提供區域變數的特定值。 只有在查詢最佳化期間,才使用這個值,在查詢執行期間,不使用這個值。 如需詳細資訊,請參閱 查詢提示。
USE AdventureWorks2022;
GO
-- Specifying expressions for OFFSET and FETCH values
DECLARE
@StartingRowNumber TINYINT = 1,
@EndingRowNumber TINYINT = 8;
SELECT DepartmentID, Name, GroupName
FROM HumanResources.Department
ORDER BY DepartmentID ASC OFFSET @StartingRowNumber - 1 ROWS
FETCH NEXT @EndingRowNumber - @StartingRowNumber + 1 ROWS ONLY
OPTION (OPTIMIZE FOR (@StartingRowNumber = 1, @EndingRowNumber = 20));
D. 指定 OFFSET 和 FETCH 值的常數純量子查詢
下列範例會使用常數純量子查詢來定義 子句的值 FETCH
。 子查詢會從 PageSize
資料表中的 dbo.AppSettings
資料行傳回單一值。
-- Specifying a constant scalar subquery
USE AdventureWorks2022;
GO
CREATE TABLE dbo.AppSettings (
AppSettingID INT NOT NULL,
PageSize INT NOT NULL
);
GO
INSERT INTO dbo.AppSettings
VALUES (1, 10);
GO
DECLARE @StartingRowNumber TINYINT = 1;
SELECT DepartmentID, Name, GroupName
FROM HumanResources.Department
ORDER BY DepartmentID ASC OFFSET @StartingRowNumber ROWS
FETCH NEXT (
SELECT PageSize
FROM dbo.AppSettings
WHERE AppSettingID = 1
) ROWS ONLY;
E. 在單一交易中執行多個查詢
下列範例示範實作分頁方案的其中一種方法,可確保所有查詢要求中傳回穩定的結果。 查詢會使用快照集隔離等級在單一交易中執行,而 子句中指定的 ORDER BY
數據行可確保數據行的唯一性。
USE AdventureWorks2022;
GO
-- Ensure the database can support the snapshot isolation level set for the query.
IF (
SELECT snapshot_isolation_state
FROM sys.databases
WHERE name = N'AdventureWorks2022'
) = 0
ALTER DATABASE AdventureWorks2022
SET ALLOW_SNAPSHOT_ISOLATION ON;
GO
-- Set the transaction isolation level to SNAPSHOT for this query.
SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
GO
-- Beginning the transaction.
BEGIN TRANSACTION;
GO
-- Declare and set the variables for the OFFSET and FETCH values.
DECLARE
@StartingRowNumber INT = 1,
@RowCountPerPage INT = 3;
-- Create the condition to stop the transaction after all rows have been returned.
WHILE (
SELECT COUNT(*)
FROM HumanResources.Department
) >= @StartingRowNumber
BEGIN
-- Run the query until the stop condition is met.
SELECT DepartmentID, Name, GroupName
FROM HumanResources.Department
ORDER BY DepartmentID ASC OFFSET @StartingRowNumber - 1 ROWS
FETCH NEXT @RowCountPerPage ROWS ONLY;
-- Increment @StartingRowNumber value.
SET @StartingRowNumber = @StartingRowNumber + @RowCountPerPage;
CONTINUE
END;
GO
COMMIT TRANSACTION;
GO
搭配 UNION、EXCEPT 和 INTERSECT 使用 ORDER BY
當查詢使用 UNION
、 EXCEPT
或 INTERSECT
運算子時, ORDER BY
必須在語句結尾指定 子句,並排序合併查詢的結果。 下列範例會傳回紅色或黃色的所有產品,並依據資料行 ListPrice
排序此組合清單。
USE AdventureWorks2022;
GO
SELECT Name, Color, ListPrice
FROM Production.Product
WHERE Color = 'Red'
-- ORDER BY cannot be specified here.
UNION ALL
SELECT Name, Color, ListPrice
FROM Production.Product
WHERE Color = 'Yellow'
ORDER BY ListPrice ASC;
範例:Azure Synapse Analytics 和 Analytics Platform System (PDW)
下列範例示範依據數值的 EmployeeKey
資料行以遞增順序排序結果集。
-- Uses AdventureWorks
SELECT EmployeeKey, FirstName, LastName
FROM DimEmployee
WHERE LastName LIKE 'A%'
ORDER BY EmployeeKey;
下列範例依據數值的 EmployeeKey
資料行以遞減順序排序結果集。
-- Uses AdventureWorks
SELECT EmployeeKey, FirstName, LastName
FROM DimEmployee
WHERE LastName LIKE 'A%'
ORDER BY EmployeeKey DESC;
下列範例依據 LastName
資料行排序結果集。
-- Uses AdventureWorks
SELECT EmployeeKey, FirstName, LastName
FROM DimEmployee
WHERE LastName LIKE 'A%'
ORDER BY LastName;
下列範例依據兩個資料行排序。 此查詢會先依據 FirstName
資料行以遞增順序排序,然後再依據 LastName
資料行以遞減順序排序共同的 FirstName
值。
-- Uses AdventureWorks
SELECT EmployeeKey, FirstName, LastName
FROM DimEmployee
WHERE LastName LIKE 'A%'
ORDER BY LastName, FirstName;