次の方法で共有


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 を使用して、INSERTUPDATEMERGE、または DELETE ステートメントの影響を受ける行を指定します。

Transact-SQL 構文表記規則

構文

SQL Server と Azure SQL Database の構文:

[
    TOP (expression) [ PERCENT ]
    [ WITH TIES ]
]

Azure Synapse Analytics および Analytics Platform System (PDW) の構文:

[
    TOP ( expression )
    [ WITH TIES ]
]

引数

式 (expression)

返す行数を指定する数値式。 を指定すると、floatPERCENT暗黙的に変換されます。 それ以外の場合、expressionbigint に変換されます。

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 句で OFFSETFETCH を使用します。 ページング ソリューション (つまり、チャンクまたは ページ データをクライアントに送信する) は、OFFSET 句と FETCH 句を使用して実装する方が簡単です。 詳細については、「SELECT - ORDER BY 句を参照してください。

SET ROWCOUNT の代わりに TOP (または OFFSETFETCH) を使用して、返される行数を制限します。 これらの方法は、次の理由から SET ROWCOUNT を使用するよりも優先されます。

  • クエリ オプティマイザーは、 ステートメントの一部として、クエリの最適化中に 句または 句で 式の値を考慮できます。 クエリを実行するステートメントの外部で SET ROWCOUNT を使用するため、その値はクエリ プランでは考慮できません。

互換性のサポート

下位互換性のために、式が整数定数の場合、SELECT ステートメントではかっこは省略可能です。 SELECT ステートメントの TOP には常にかっこを使用することをお勧めします。 これにより、INSERTUPDATEMERGE、および DELETE ステートメントで必要な使用との整合性が確保されます。

相互運用性

TOP 式は、トリガーが原因で実行される可能性があるステートメントには影響しません。 トリガーの inserted テーブルと deleted テーブルは、INSERTUPDATEMERGE、または DELETE ステートメントによって本当に影響を受ける行のみを返します。 たとえば、INSERT TRIGGER が、TOP 句を使用した INSERT ステートメントの結果として発生した場合です。

SQL Server では、ビューを使用した行の更新ができます。 ビュー定義に TOP 句を含めることができるため、更新によって行が TOP 式の要件を満たさなくなった場合、特定の行がビューから消える可能性があります。

ステートメントで指定した場合、 句は、ソース テーブル全体とターゲット テーブル全体が結合 後に 適用されます。 また、結合された行で挿入、更新、または削除操作の対象にならないものは削除されます。 TOP 句は、指定した値に結合された行の数をさらに減らし、挿入、更新、または削除アクションは順序付けされていない方法で残りの結合された行に適用されます。 つまり、WHEN 句で定義されているアクション間で行が分散される順序はありません。 たとえば、TOP (10) を指定すると 10 行に影響する場合、これらの行のうち 7 行が更新され、3 行が挿入される可能性があります。 または、1 つは削除され、5 つは更新され、4 つは挿入される可能性があります。 MERGE ステートメントはソース テーブルとターゲット テーブルの両方の完全なテーブル スキャンを実行するため、TOP 句を使用して複数のバッチを作成して大きなテーブルを変更すると、I/O パフォーマンスが影響を受ける可能性があります。 このシナリオでは、連続するすべてのバッチで確実に新しい行が対象になっていることが重要です。

UNIONUNION ALLEXCEPT、または 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

サブセレクト操作で TOPORDER BY を使用すると、ORDER BY 句の結果が TOP 句に適用され、UNION 操作の結果を並べ替えないようにすることができます。

結果セットを次に示します。

 Model         Color      Price
 ------------- ---------- -------
 sedan         red        10000.00
 van           blue        8000.00

制限

INSERTUPDATEMERGE、または DELETETOP を使用する場合、参照される行は順序付けされません。 また、これらのステートメントで ORDER BY 句を直接指定することはできません。 TOP を使用して、意味のある時系列の順序で行を挿入、削除、または変更する必要がある場合は、サブセレクト ステートメントで指定された ORDER BY 句で TOP を使用します。 この記事の セクションを参照してください。

パーティション ビューの UPDATE ステートメントまたは DELETE ステートメントでは、TOP を使用できません。

同じクエリ式 (同じクエリ スコープ内) で TOPOFFSET および FETCH と組み合わせることはできません。 詳細については、「SELECT - ORDER BY 句を参照してください。

この記事の Transact-SQL コード サンプルでは、AdventureWorks2022 または AdventureWorksDW2022 サンプル データベースを使用します。このサンプル データベースは、Microsoft SQL Server サンプルとコミュニティ プロジェクト ホーム ページからダウンロードできます。

カテゴリ 主な構文要素
基本構文 TOP * PERCENT
同順位の値を含む WITH TIES
DELETE、INSERT、または UPDATE の影響を受ける行の制限 DELETEINSERTUPDATE

基本構文

このセクションの例では、最低限必要な構文を使用して、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 を使用して削除された行数を制限する

DELETETOP (<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 BYTOP を使用します。 次のクエリでは、納期が早いものから 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 BYTOP を使用します。 次の例は、これを行う方法を示しています。 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 句を使用してテーブル内の行を更新します。 UPDATETOP (<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 人であるためです。