TOP (Transact-SQL)
適用対象:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceAzure Synapse AnalyticsAnalytics Platform System (PDW)Microsoft Fabric の SQL 分析エンドポイントMicrosoft Fabric WarehouseMicrosoft Fabric SQL Database
SQL Server で、クエリの結果セットとして返される行を、指定した行の数または割合に制限します。
ORDER BY
句で TOP
を使用する場合、結果セットは、順序付けられた行の最初の n 数に制限されます。 それ以外の場合、TOP
は、未定義の順序で最初の n 行数を返します。 この句を使用して、SELECT
ステートメントから返される行数を指定します。 または、TOP
を使用して、INSERT
、UPDATE
、MERGE
、または DELETE
ステートメントの影響を受ける行を指定します。
構文
SQL Server と Azure SQL Database の構文:
[
TOP (expression) [ PERCENT ]
[ WITH TIES ]
]
Azure Synapse Analytics および Analytics Platform System (PDW) の構文:
[
TOP ( expression )
[ WITH TIES ]
]
引数
式 (expression)
返す行数を指定する数値式。
式 を指定すると、float 値 PERCENT
暗黙的に変換されます。 それ以外の場合、expression は bigint に変換されます。
PERCENT
クエリの結果セットの先頭から、expression で指定したパーセントの行のみを返すように指定します。 小数値は整数値に切り上げられます。
WITH TIES
制限された結果セットの最後の場所にある複数の行を返します。 この引数は、ORDER BY
句と共に使用する必要があります。 5
に設定されていても、さらに 2 つの行が行 5 の ORDER BY
列の値と一致する場合、結果セットには 7 行が含まれます。
TOP
句は、WITH TIES
引数を使用して、SELECT
ステートメントでのみ指定でき、ORDER BY
句も指定した場合にのみ指定できます。 同順位のレコードが返される順序は任意です。
ORDER BY
は、この規則には影響しません。
ベスト プラクティス
SELECT
ステートメントでは、常に TOP
句と共に ORDER BY
句を使用します。 これは、TOP
の影響を受ける行を予測可能に示す唯一の方法です。
クエリ ページング ソリューションを実装するには、TOP
句の代わりに ORDER BY
句で OFFSET
と FETCH
を使用します。 ページング ソリューション (つまり、チャンクまたは ページ データをクライアントに送信する) は、OFFSET
句と FETCH
句を使用して実装する方が簡単です。 詳細については、「SELECT - ORDER BY 句
SET ROWCOUNT
の代わりに TOP
(または OFFSET
と FETCH
) を使用して、返される行数を制限します。 これらの方法は、次の理由から SET ROWCOUNT
を使用するよりも優先されます。
- クエリ オプティマイザーは、
ステートメントの一部として、クエリの最適化中に 句または 句で 式の値を考慮できます。 クエリを実行するステートメントの外部で SET ROWCOUNT
を使用するため、その値はクエリ プランでは考慮できません。
互換性のサポート
下位互換性のために、式が整数定数の場合、SELECT
ステートメントではかっこは省略可能です。
SELECT
ステートメントの TOP
には常にかっこを使用することをお勧めします。 これにより、INSERT
、UPDATE
、MERGE
、および DELETE
ステートメントで必要な使用との整合性が確保されます。
相互運用性
TOP
式は、トリガーが原因で実行される可能性があるステートメントには影響しません。 トリガーの inserted
テーブルと deleted
テーブルは、INSERT
、UPDATE
、MERGE
、または DELETE
ステートメントによって本当に影響を受ける行のみを返します。 たとえば、INSERT TRIGGER
が、TOP
句を使用した INSERT
ステートメントの結果として発生した場合です。
SQL Server では、ビューを使用した行の更新ができます。 ビュー定義に TOP
句を含めることができるため、更新によって行が TOP
式の要件を満たさなくなった場合、特定の行がビューから消える可能性があります。
TOP
句は、指定した値に結合された行の数をさらに減らし、挿入、更新、または削除アクションは順序付けされていない方法で残りの結合された行に適用されます。 つまり、WHEN
句で定義されているアクション間で行が分散される順序はありません。 たとえば、TOP (10)
を指定すると 10 行に影響する場合、これらの行のうち 7 行が更新され、3 行が挿入される可能性があります。 または、1 つは削除され、5 つは更新され、4 つは挿入される可能性があります。
MERGE
ステートメントはソース テーブルとターゲット テーブルの両方の完全なテーブル スキャンを実行するため、TOP
句を使用して複数のバッチを作成して大きなテーブルを変更すると、I/O パフォーマンスが影響を受ける可能性があります。 このシナリオでは、連続するすべてのバッチで確実に新しい行が対象になっていることが重要です。
UNION
、UNION ALL
、EXCEPT
、または INTERSECT
演算子を含むクエリで TOP
句を指定する場合は注意が必要です。
TOP
句と ORDER BY
句が論理的に処理される順序が、選択操作でこれらの演算子を使用する場合、常に直感的とは限らないため、予期しない結果を返すクエリを記述できます。 たとえば、次のテーブルとデータがある場合に、最も安価な赤色の自動車と青色の自動車 (つまり赤色のセダンと青色のバン) を取得する必要があるとします。
CREATE TABLE dbo.Cars
(
Model VARCHAR (15),
Price MONEY,
Color VARCHAR (10)
);
INSERT dbo.Cars
VALUES ('sedan', 10000, 'red'),
('convertible', 15000, 'blue'),
('coupe', 20000, 'red'),
('van', 8000, 'blue');
これらの結果を得るためには、次のクエリを記述します。
SELECT TOP (1) Model, Color, Price
FROM dbo.Cars
WHERE Color = 'red'
UNION ALL
SELECT TOP (1) Model, Color, Price
FROM dbo.Cars
WHERE Color = 'blue'
ORDER BY Price ASC;
GO
結果セットを次に示します。
Model Color Price
------------- ---------- -------
sedan red 10000.00
convertible blue 15000.00
予期しない結果が返されるのは、TOP
句が演算子の結果を並べ替える ORDER BY
句の前に論理的に実行されるためです (この場合UNION ALL
)。 したがって、前のクエリでは任意の赤色の自動車と青色の自動車が 1 つずつ返され、その和集合の結果が価格で並べ替えられます。 目的の結果を得るための正しいクエリの例を次に示します。
SELECT Model, Color, Price
FROM (SELECT TOP (1) Model, Color, Price
FROM dbo.Cars
WHERE Color = 'red'
ORDER BY Price ASC) AS a
UNION ALL
SELECT Model, Color, Price
FROM (SELECT TOP (1) Model, Color, Price
FROM dbo.Cars
WHERE Color = 'blue'
ORDER BY Price ASC) AS b;
GO
サブセレクト操作で TOP
と ORDER BY
を使用すると、ORDER BY
句の結果が TOP
句に適用され、UNION
操作の結果を並べ替えないようにすることができます。
結果セットを次に示します。
Model Color Price
------------- ---------- -------
sedan red 10000.00
van blue 8000.00
制限
INSERT
、UPDATE
、MERGE
、または DELETE
で TOP
を使用する場合、参照される行は順序付けされません。 また、これらのステートメントで ORDER BY
句を直接指定することはできません。
TOP
を使用して、意味のある時系列の順序で行を挿入、削除、または変更する必要がある場合は、サブセレクト ステートメントで指定された ORDER BY
句で TOP
を使用します。 この記事の 例 セクションを参照してください。
パーティション ビューの UPDATE
ステートメントまたは DELETE
ステートメントでは、TOP
を使用できません。
同じクエリ式 (同じクエリ スコープ内) で TOP
を OFFSET
および FETCH
と組み合わせることはできません。 詳細については、「SELECT - ORDER BY 句
例
この記事の Transact-SQL コード サンプルでは、AdventureWorks2022
または AdventureWorksDW2022
サンプル データベースを使用します。このサンプル データベースは、Microsoft SQL Server サンプルとコミュニティ プロジェクト ホーム ページからダウンロードできます。
カテゴリ | 主な構文要素 |
---|---|
基本構文 | TOP * PERCENT |
同順位の値を含む | WITH TIES |
DELETE、INSERT、または UPDATE の影響を受ける行の制限 |
DELETE 、INSERT 、UPDATE |
基本構文
このセクションの例では、最低限必要な構文を使用して、ORDER BY
句の基本的な機能を示します。
A. 定数値で TOP を使用する
次の例では、クエリの結果セットで返される従業員の数を、定数値を使用して指定します。 最初の例では、ORDER BY
句が使用されていないため、最初の 10 行の未定義の行が返されます。 2 番目の例では、最近採用された上位 10 人の従業員を返すために、ORDER BY
句を使用します。
USE AdventureWorks2022;
GO
-- Select the first 10 random employees.
SELECT TOP (10) JobTitle, HireDate
FROM HumanResources.Employee;
GO
-- Select the first 10 employees hired most recently.
SELECT TOP (10) JobTitle, HireDate
FROM HumanResources.Employee
ORDER BY HireDate DESC;
GO
B. 変数で TOP を使用する
次の例では、クエリの結果セットで返される従業員の数を、変数を使用して指定します。
USE AdventureWorks2022;
GO
DECLARE @p AS INT = 10;
SELECT TOP (@p) JobTitle, HireDate, VacationHours
FROM HumanResources.Employee
ORDER BY VacationHours DESC;
GO
C. パーセンテージを指定する
次の例では、PERCENT
を使用して、クエリ結果セットで返される従業員の数を指定します。
HumanResources.Employee
テーブルには、290 人の従業員が記録されています。 290 の 5% は小数を含む値なので、整数に切り上げられます。
USE AdventureWorks2022;
GO
SELECT TOP (5) PERCENT JobTitle, HireDate
FROM HumanResources.Employee
ORDER BY HireDate DESC;
GO
タイ値を含める
A. WITH TIES を使用して、最後の行の値と一致する行を含める
次の例では、給与の高い上位 10
% の全従業員を取得し、結果を給与の降順で返します。
WITH TIES
を指定すると、返された最も低い給与 (最後の行) と同じ給与の従業員も返されるので、結果は全従業員の 10
% を超える場合があります。
USE AdventureWorks2022;
GO
SELECT TOP (10) PERCENT WITH TIES pp.FirstName,
pp.LastName,
e.JobTitle,
e.Gender,
r.Rate
FROM Person.Person AS pp
INNER JOIN HumanResources.Employee AS e
ON pp.BusinessEntityID = e.BusinessEntityID
INNER JOIN HumanResources.EmployeePayHistory AS r
ON r.BusinessEntityID = e.BusinessEntityID
ORDER BY Rate DESC;
GO
DELETE、INSERT、または UPDATE の影響を受ける行を制限する
A. TOP を使用して削除された行数を制限する
DELETE
で TOP (<n>)
句を使用すると、n 行数の未定義の選択に対して削除操作が実行されます。 つまり、DELETE
ステートメントは、WHERE
句で定義されている条件を満たす任意の (n) 行数を選択します。 次の例では、納期が 2002 年 7 月 1 日より早い 20
行を PurchaseOrderDetail
テーブルから選択して削除します。
USE AdventureWorks2022;
GO
DELETE TOP (20)
FROM Purchasing.PurchaseOrderDetail
WHERE DueDate < '20020701';
GO
TOP
を使用して、意味のある時系列の順序で行を削除する場合は、副選択ステートメントで ORDER BY
で TOP
を使用します。 次のクエリでは、納期が早いものから 10 行を PurchaseOrderDetail
テーブルから削除します。 10 行だけを確実に削除するために、サブセレクト ステートメントではテーブルの主キーの列 (PurchaseOrderID
) を指定しています。 サブセレクト ステートメントでキー以外の列を使用すると、指定した列に重複する値が含まれている場合、10 行を超える行が削除される可能性があります。
USE AdventureWorks2022;
GO
DELETE Purchasing.PurchaseOrderDetail
WHERE PurchaseOrderDetailID IN (
SELECT TOP 10 PurchaseOrderDetailID
FROM Purchasing.PurchaseOrderDetail
ORDER BY DueDate ASC
);
GO
B. TOP を使用して挿入される行数を制限する
次の例では、EmployeeSales
テーブルを作成し、上位 5 人の従業員の名前と年度累計売り上げデータを HumanResources.Employee
テーブルから挿入します。
INSERT
ステートメントは、WHERE
句で定義されている条件を満たす、SELECT
ステートメントによって返される任意の 5 つの行を選択します。
OUTPUT
句には、EmployeeSales
テーブルに挿入された行が表示されます。
SELECT
ステートメントの ORDER BY
句は、上位 5 人の従業員を特定するために使用されません。
USE AdventureWorks2022;
GO
IF OBJECT_ID('dbo.EmployeeSales', 'U') IS NOT NULL
DROP TABLE dbo.EmployeeSales;
GO
CREATE TABLE dbo.EmployeeSales
(
EmployeeID NVARCHAR (11) NOT NULL,
LastName NVARCHAR (20) NOT NULL,
FirstName NVARCHAR (20) NOT NULL,
YearlySales MONEY NOT NULL
);
GO
INSERT TOP (5) INTO dbo.EmployeeSales
OUTPUT
inserted.EmployeeID,
inserted.FirstName,
inserted.LastName,
inserted.YearlySales
SELECT sp.BusinessEntityID,
c.LastName,
c.FirstName,
sp.SalesYTD
FROM Sales.SalesPerson AS sp
INNER JOIN Person.Person AS c
ON sp.BusinessEntityID = c.BusinessEntityID
WHERE sp.SalesYTD > 250000.00
ORDER BY sp.SalesYTD DESC;
GO
TOP
を使用して、意味のある時系列の順序で行を挿入する場合は、サブセレクト ステートメントで ORDER BY
で TOP
を使用します。 次の例は、これを行う方法を示しています。
OUTPUT
句には、EmployeeSales
テーブルに挿入された行が表示されます。 上位 5 人の従業員が、未定義の行ではなく、ORDER BY
句の結果に基づいて挿入されるようになりました。
INSERT INTO dbo.EmployeeSales
OUTPUT
inserted.EmployeeID,
inserted.FirstName,
inserted.LastName,
inserted.YearlySales
SELECT TOP (5) sp.BusinessEntityID,
c.LastName,
c.FirstName,
sp.SalesYTD
FROM Sales.SalesPerson AS sp
INNER JOIN Person.Person AS c
ON sp.BusinessEntityID = c.BusinessEntityID
WHERE sp.SalesYTD > 250000.00
ORDER BY sp.SalesYTD DESC;
GO
C. TOP を使用して更新される行数を制限する
次の例では、TOP
句を使用してテーブル内の行を更新します。
UPDATE
で TOP (<n>)
句を使用すると、未定義の行数で更新操作が実行されます。 つまり、UPDATE
ステートメントは、WHERE
句で定義されている条件を満たす任意の (n) 行数を選択します。 次の例では、ある販売員の顧客から 10 人を抽出して別の販売員に割り当てています。
USE AdventureWorks2022;
UPDATE TOP (10)
Sales.Store
SET SalesPersonID = 276
WHERE SalesPersonID = 275;
GO
TOP
を使用して意味のある時系列で更新プログラムを適用する必要がある場合は、サブセレクト ステートメントの ORDER BY
と共に TOP
を使用する必要があります。 次の例では、採用日の古い従業員上位 10 人の休暇時間を更新します。
UPDATE HumanResources.Employee
SET VacationHours = VacationHours + 8
FROM (SELECT TOP 10 BusinessEntityID
FROM HumanResources.Employee
ORDER BY HireDate ASC) AS th
WHERE HumanResources.Employee.BusinessEntityID = th.BusinessEntityID;
GO
例: Azure Synapse Analytics、Analytics Platform System (PDW)
次の例では、クエリ条件に一致する上位 31 行を返します。
ORDER BY
句を使用すると、返された 31 行が、LastName
列のアルファベット順に基づいて最初の 31 行になります。
タイを指定せずに TOP
を使用する。
SELECT TOP (31) FirstName, LastName
FROM DimEmployee
ORDER BY LastName;
結果: 31 行が返されます。
TOP
を使用して、WITH TIES
を指定します。
SELECT TOP (31) WITH TIES FirstName, LastName
FROM DimEmployee
ORDER BY LastName;
結果: 33 行が返されます。これは、31 番目の行 Brown
同じ名前の従業員が 3 人であるためです。
関連コンテンツ
- SELECT (Transact-SQL)
- INSERT (Transact-SQL)
- UPDATE (Transact-SQL)
- DELETE (Transact-SQL)
- SELECT - ORDER BY 句 (Transact-SQL) を
- SET ROWCOUNT (Transact-SQL)
- MERGE (Transact-SQL)