sql >> データベース >  >> RDS >> Sqlserver

OFFSET/FETCHを使用したSQLServerでのページネーション

    ページ付けは、ユーザーが前へをクリックできるアプリケーションでよく使用されます。 /次へ 結果を構成するページをナビゲートするか、ページ番号をクリックして特定のページに直接移動します。

    SQL Serverでクエリを実行する場合、OFFSETを使用して結果をページ分割できます。 およびFETCH ORDER BYの引数 句。これらの引数はSQLServer2012で導入されたため、SQLServer2012以降を使用している場合はこの手法を使用できます。

    このコンテキストでは、ページ付けとは、クエリ結果を小さなチャンクに分割する場所であり、各チャンクは前のチャンクが終了したところから継続します。たとえば、クエリが1000行を返す場合、100行のグループで返されるようにページ分割できます。アプリケーションは、ページ番号とページサイズをSQL Serverに渡すことができ、SQLServerはそれを使用して要求されたページのデータ。

    例1-ページネーションなし

    まず、テーブル内のすべての行を返すクエリを実行しましょう。

    SELECT *
    FROM Genres
    ORDER BY GenreId;
    

    結果:

    +-----------+---------+
    | GenreId   | Genre   |
    |-----------+---------|
    | 1         | Rock    |
    | 2         | Jazz    |
    | 3         | Country |
    | 4         | Pop     |
    | 5         | Blues   |
    | 6         | Hip Hop |
    | 7         | Rap     |
    | 8         | Punk    |
    +-----------+---------+
    

    この例ではページネーションを使用していません–すべての結果が表示されます。

    この結果セットは非常に小さいため、通常はページネーションは必要ありませんが、この記事の目的上、ページネーションを行いましょう。

    例2–最初の3つの結果を表示する

    この例では、最初の3つの結果を表示します。

    SELECT *
    FROM Genres
    ORDER BY GenreId
      OFFSET 0 ROWS
      FETCH NEXT 3 ROWS ONLY;
    

    結果:

    +-----------+---------+
    | GenreId   | Genre   |
    |-----------+---------|
    | 1         | Rock    |
    | 2         | Jazz    |
    | 3         | Country |
    +-----------+---------+
    

    この場合、結果は最初の結果から開始し、次の3行を表示するように指定します。これは、以下を使用して行われます。

    • OFFSET 0 ROWS オフセット(ゼロのオフセット)があってはならないことを指定します。
    • FETCH NEXT 3 ROWS ONLY オフセットから次の3行を取得します。ゼロのオフセットを指定したので、最初の3行がフェッチされます。

    上位3つの結果だけが必要な場合は、TOPを使用して同じ結果を達成できたはずです。 オフセット値とフェッチ値を指定する代わりに句。ただし、これでは次の部分を実行できませんでした。

    例3–次の3つの結果を表示する

    次の3つの結果を表示しましょう:

    SELECT *
    FROM Genres
    ORDER BY GenreId
      OFFSET 3 ROWS
      FETCH NEXT 3 ROWS ONLY;
    

    結果:

    +-----------+---------+
    | GenreId   | Genre   |
    |-----------+---------|
    | 4         | Pop     |
    | 5         | Blues   |
    | 6         | Hip Hop |
    +-----------+---------+
    

    ですから、私が変更したのはオフセットだけでした。

    オフセット値とフェッチ値は、変数、パラメーター、または定数スカラーサブクエリとして提供される式にすることもできます。サブクエリを使用する場合、外部クエリスコープで定義されている列を参照することはできません(外部クエリと関連付けることはできません)。

    次の例では、式を使用して、結果をページ分割する2つのアプローチを示しています。

    例4–行番号によるページネーション

    この例では、式を使用してを指定します 開始する番号。

    DECLARE 
      @StartRow int = 1,
      @RowsPerPage int = 3;
      
    SELECT *  
    FROM Genres
    ORDER BY GenreId ASC
        OFFSET @StartRow - 1 ROWS
        FETCH NEXT @RowsPerPage ROWS ONLY;
    

    結果:

    +-----------+---------+
    | GenreId   | Genre   |
    |-----------+---------|
    | 1         | Rock    |
    | 2         | Jazz    |
    | 3         | Country |
    +-----------+---------+
    

    ここでは、@StartRow int = 1を使用します 結果を最初の行から開始するように指定します。

    その値を2にインクリメントするとどうなりますか。 。

    DECLARE 
      @StartRow int = 2,
      @RowsPerPage int = 3;
      
    SELECT *  
    FROM Genres
    ORDER BY GenreId ASC
        OFFSET @StartRow - 1 ROWS
        FETCH NEXT @RowsPerPage ROWS ONLY;
    

    結果:

    +-----------+---------+
    | GenreId   | Genre   |
    |-----------+---------|
    | 2         | Jazz    |
    | 3         | Country |
    | 4         | Pop     |
    +-----------+---------+
    

    2列目から始まります。この方法を使用して、開始する正確な行を指定できます。

    例5–ページ番号によるページネーション

    この例は、行番号ではなくページ番号を指定できることを除いて、前の例とほとんど同じです。

    DECLARE 
      @PageNumber int = 1,
      @RowsPerPage int = 3;
      
    SELECT *  
    FROM Genres
    ORDER BY GenreId ASC
        OFFSET (@PageNumber - 1) * @RowsPerPage ROWS
        FETCH NEXT @RowsPerPage ROWS ONLY;
    

    結果:

    +-----------+---------+
    | GenreId   | Genre   |
    |-----------+---------|
    | 1         | Rock    |
    | 2         | Jazz    |
    | 3         | Country |
    +-----------+---------+
    

    したがって、最初の結果は同じです。ただし、@PageNumberをインクリメントするとどうなるか見てみましょう。 2へ (新しい目的を反映するために、この変数の名前を変更しました。)

    DECLARE 
      @PageNumber int = 2,
      @RowsPerPage int = 3;
      
    SELECT *  
    FROM Genres
    ORDER BY GenreId ASC
        OFFSET (@PageNumber - 1) * @RowsPerPage ROWS
        FETCH NEXT @RowsPerPage ROWS ONLY;
    

    結果:

    +-----------+---------+
    | GenreId   | Genre   |
    |-----------+---------|
    | 4         | Pop     |
    | 5         | Blues   |
    | 6         | Hip Hop |
    +-----------+---------+
    

    今回の結果は4行目から始まります。したがって、このメソッドを使用すると、行番号ではなくページ番号を渡すだけで済みます。

    例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;  
    CONTINUE
    END;
    

    結果:

    +-----------+---------+
    | 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–行と行

    ROWを使用するコードに遭遇した場合 ROWSの代わりに 、両方の引数は同じことをします。これらは同義語であり、ANSI互換性のために提供されています。

    これがこのページの最初の例ですが、ROW ROWSの代わりに 。

    SELECT *
    FROM Genres
    ORDER BY GenreId
      OFFSET 0 ROW
      FETCH NEXT 3 ROW ONLY;
    

    結果:

    +-----------+---------+
    | GenreId   | Genre   |
    |-----------+---------|
    | 1         | Rock    |
    | 2         | Jazz    |
    | 3         | Country |
    +-----------+---------+
    

    例8– FIRST vs NEXT

    同じことがFIRSTにも当てはまります およびNEXT 。これらは、ANSI互換性のために提供されている同義語です。

    これは前の例ですが、FIRST NEXTの代わりに 。

    SELECT *
    FROM Genres
    ORDER BY GenreId
      OFFSET 0 ROW
      FETCH FIRST 3 ROW ONLY;
    

    結果:

    +-----------+---------+
    | GenreId   | Genre   |
    |-----------+---------|
    | 1         | Rock    |
    | 2         | Jazz    |
    | 3         | Country |
    +-----------+---------+
    

    1. 複数の列にわたるDISTINCTのカウント

    2. SQL Serverで「smalldatetime」を「datetime」に変換する(T-SQLの例)

    3. ASP.NET Core MVC、Entity Framework Core、およびSQLServerを使用したCRUD操作

    4. 単一の列の値を複数の列の値に分割するにはどうすればよいですか?