ページネーションは、ユーザーが前/次をクリックして結果を構成するページを移動したり、ページ番号をクリックして特定のページに直接移動したりSQL Serverでクエリを実行するときは、OFFSET
FETCH
ORDER BY
句の引数。 これらの引数はSQL Server2012で導入されたため、SQL Server2012以降を使用している場合は、この手法を使用できます。
このコンテキストでは、ページネーションは、クエリ結果をより小さなチャンクに分割し、各チャンクは前の終了した場所を継続します。 たとえば、クエリが1000行を返す場合は、100行のグループで返されるようにページ分割することができます。 アプリケーションはページ番号とページサイズをSQL Serverに渡すことができ、SQL Serverはそれを使用して要求されたページのデータだけを返すことができます。
例1–ページネーションなし
まず、テーブル内のすべての行を返すクエリを実行しましょう。
SELECT *FROM GenresORDER BY GenreId;
Result:
+-----------+---------+| GenreId | Genre ||-----------+---------|| 1 | Rock || 2 | Jazz || 3 | Country || 4 | Pop || 5 | Blues || 6 | Hip Hop || 7 | Rap || 8 | Punk |+-----------+---------+
この例では、ページネーションを使用しません–すべての結果が表示されます。
この結果セットは非常に小さいので、通常はページネーションを必要としませんが、この記事の目的のために、ページネーションをしましょう。
例2–最初の3つの結果を表示する
この例では、最初の3つの結果が表示されます。
SELECT *FROM GenresORDER BY GenreId OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY;
Result:
+-----------+---------+| GenreId | Genre ||-----------+---------|| 1 | Rock || 2 | Jazz || 3 | Country |+-----------+---------+
この場合、結果は最初の結果から始まり、次の3行を表示するように指定します。 これは、次を使用して行われます:
OFFSET 0 ROWS
オフセット(ゼロのオフセット)があってはならないことを指定します。FETCH NEXT 3 ROWS ONLY
オフセットから次の三つの行を取得します。 オフセットをゼロに指定したので、最初の3行がフェッチされます。必要なのが上位3つの結果だけであれば、offsetとfetchの値を指定する代わりにTOP
句を使用することで同じ結果を達成できました。 しかし、これは私たちが次の部分を行うことはできませんでした。
例3–次の3つの結果を表示します
次の3つの結果を表示しましょう:
SELECT *FROM GenresORDER BY GenreId OFFSET 3 ROWS FETCH NEXT 3 ROWS ONLY;
結果:
+-----------+---------+| GenreId | Genre ||-----------+---------|| 4 | Pop || 5 | Blues || 6 | Hip Hop |+-----------+---------+
だから、私が変更した唯一のものはオフセットでした。
オフセット値とフェッチ値は、変数、パラメーター、または定数スカラサブクエリとして提供される式にすることもできます。 サブクエリが使用される場合、外部クエリスコープで定義された列を参照することはできません(外部クエリと相関することはできません)。
次の例では、式を使用して、結果をページ分割する2つの方法を示します。
例4–行番号によるページネーション
この例では、式を使用して開始する行番号を指定します。ここでは、
@StartRow int = 1
2
にインクリメントすると、次のようになります。結果:+-----------+---------+| GenreId | Genre ||-----------+---------|| 2 | Jazz || 3 | Country || 4 | Pop |+-----------+---------+
2番目の行から始まります。 この方法を使用して、開始する正確な行を指定できます。
例5–ページ番号によるページネーション
この例は、行番号ではなくページ番号を指定できる点を除いて、前の例とほぼ同じです。 結果:
+-----------+---------+| GenreId | Genre ||-----------+---------|| 1 | Rock || 2 | Jazz || 3 | Country |+-----------+---------+
最初の結果は同じです。 ただし、
@PageNumber
2
にインクリメントするとどうなるか見てみましょう(この変数の名前は新しい目的p>DECLARE @PageNumber int = 2, @RowsPerPage int = 3; SELECT * FROM GenresORDER BY GenreId ASC OFFSET (@PageNumber - 1) * @RowsPerPage ROWS FETCH NEXT @RowsPerPage ROWS ONLY;
結果:
+-----------+---------+| GenreId | Genre ||-----------+---------|| 4 | Pop || 5 | Blues || 6 | Hip Hop |+-----------+---------+
今回は結果が四行目から始まります。 したがって、このメソッドを使用すると、行番号ではなくページ番号を渡すことができます。
例6–ページネーションループ
終了するには、すべてのページをループし、各反復の開始行番号を指定する簡単な例を次に示します。
DECLARE @StartRow int = 1, @RowsPerPage int = 3;WHILE (SELECT COUNT(*) FROM Genres) >= @StartRow BEGIN SELECT * FROM Genres ORDER BY GenreId ASC OFFSET @StartRow - 1 ROWS FETCH NEXT @RowsPerPage ROWS ONLY;SET @StartRow = @StartRow + @RowsPerPage; CONTINUEEND;
結果:
+-----------+---------+| GenreId | Genre ||-----------+---------|| 1 | Rock || 2 | Jazz || 3 | Country |+-----------+---------+(3 rows affected)+-----------+---------+| GenreId | Genre ||-----------+---------|| 4 | Pop || 5 | Blues || 6 | Hip Hop |+-----------+---------+(3 rows affected)+-----------+---------+| GenreId | Genre ||-----------+---------|| 7 | Rap || 8 | Punk |+-----------+---------+(2 rows affected)
例7–行対行
+-----------+---------+| GenreId | Genre ||-----------+---------|| 1 | Rock || 2 | Jazz || 3 | Country |+-----------+---------+(3 rows affected)+-----------+---------+| GenreId | Genre ||-----------+---------|| 4 | Pop || 5 | Blues || 6 | Hip Hop |+-----------+---------+(3 rows affected)+-----------+---------+| GenreId | Genre ||-----------+---------|| 7 | Rap || 8 | Punk |+-----------+---------+(2 rows affected)
例7-行対行
+-----------+---------+| GenreId | Genre ||-----------+---------|| 1 | Rock || 2 | Jazz || 3 | Country |+-----------+---------+(3 rows affected)+-----------+---------+| GenreId | Genre ||-----------+---------|| 4 | Pop || 5 | Blues || 6 | Hip Hop |+-----------+---------+(3 rows affected)+-----------+---------+| GenreId | Genre ||-----------+---------|| 7 | Rap || 8 | Punk |+-----------+---------+(2 rows affected)
+-----------+---------+| GenreId | Genre ||-----------+---------|| 1 | Rock || 2 | Jazz || 3 | Country |+-----------+---------+(3 rows affected)+-----------+---------+| GenreId | Genre ||-----------+---------|| 4 | Pop || 5 | Blues || 6 | Hip Hop |+-----------+---------+(3 rows affected)+-----------+---------+| GenreId | Genre ||-----------+---------|| 7 | Rap || 8 | Punk |+-----------+---------+(2 rows affected)
+-----------+---------+| GenreId | Genre ||-----------+---------|| 1 | Rock || 2 | Jazz || 3 | Country |+-----------+---------+(3 rows affected)+-----------+---------+| GenreId | Genre ||-----------+---------|| 4 | Pop || 5 | Blues || 6 | Hip Hop |+-----------+---------+(3 rows affected)+-----------+---------+| GenreId | Genre ||-----------+---------|| 7 | Rap || 8 | Punk |+-----------+---------+(2 rows affected)
+-----------+---------+| GenreId | Genre ||-----------+---------|| 1 | Rock || 2 | Jazz || 3 | Country |+-----------+---------+(3 rows affected)+-----------+---------+| GenreId | Genre ||-----------+---------|| 4 | Pop || 5 | Blues || 6 | Hip Hop |+-----------+---------+(3 rows affected)+-----------+---------+| GenreId | Genre ||-----------+---------|| 7 | Rap || 8 | Punk |+-----------+---------+(2 rows affected)
ROW
ROWS
の代わりに、両方の引数が同じことを行います。 これらは同義語であり、ANSI互換のために提供されています。 このページの最初の例は次のとおりですが、ROW
ROWS
。SELECT *FROM GenresORDER BY GenreId OFFSET 0 ROW FETCH NEXT 3 ROW ONLY;
結果:
+-----------+---------+| GenreId | Genre ||-----------+---------|| 1 | Rock || 2 | Jazz || 3 | Country |+-----------+---------+
例8–最初と次の
同じことが
FIRST
NEXT
に適用されます。 これらはANSI互換性のために提供される同義語です。これは前の例ですが、NEXT
FIRST
を使用しています。p>SELECT *FROM GenresORDER BY GenreId OFFSET 0 ROW FETCH FIRST 3 ROW ONLY;
結果:p>
+-----------+---------+| GenreId | Genre ||-----------+---------|| 1 | Rock || 2 | Jazz || 3 | Country |+-----------+---------+