web-dev-qa-db-ja.com

OFFSET / FETCH NEXTから合計行数を取得する

そのため、Webサイトにページングを実装したいレコードの数を返す関数があります。これを実現するには、SQL Server 2012のOffset/Fetch Nextを使用することをお勧めしました。私たちのウェブサイトには、レコードの総数とその時点でどのページにいるかをリストするエリアがあります。

以前は、レコードセット全体を取得し、プログラムでページングを構築できました。しかし、FETCH NEXT X ROWS ONLYでSQLの方法を使用すると、X行しか返されないため、合計レコードセットが何であるか、および最小ページと最大ページを計算する方法がわかりません。これを行うことができる唯一の方法は、関数を2回呼び出して、最初の行で行数をカウントしてから、2番目の行をFETCH NEXTで実行することです。クエリを2回実行しなくてもよい方法はありますか?パフォーマンスを遅くするのではなく、スピードを上げようとしています。

77
CrystalBlue

COUNT(*) OVER()を使用できます...ここに_sys.all_objects_を使用した簡単な例を示します。

_DECLARE 
  @PageSize INT = 10, 
  @PageNum  INT = 1;

SELECT 
  name, object_id, 
  overall_count = COUNT(*) OVER()
FROM sys.all_objects
ORDER BY name
  OFFSET (@PageNum-1)*@PageSize ROWS
  FETCH NEXT @PageSize ROWS ONLY;
_

ただし、これは小さなデータセット用に予約する必要があります。大規模なセットでは、パフォーマンスがひどくなります。 より良い代替策については、このPaul Whiteの記事を参照 、インデックス付きビューの維持(結果がフィルター処理されていないか、WHERE句を事前に知っている場合のみ機能します)およびROW_NUMBER()トリック。

99
Aaron Bertrand

COUNT()OVER()メソッドを使用してパフォーマンスの問題が発生しました(10レコードを返すのに40秒かかり、その後問題がなかったため、サーバーであるかどうかはわかりません)。この手法は、COUNT()OVER()を使用せずにすべての条件下で機能し、同じことを実現します。

DECLARE 
    @PageSize INT = 10, 
    @PageNum  INT = 1;

WITH TempResult AS(
    SELECT ID, Name
    FROM Table
), TempCount AS (
    SELECT COUNT(*) AS MaxRows FROM TempResult
)
SELECT *
FROM TempResult, TempCount
ORDER BY TempResult.Name
    OFFSET (@PageNum-1)*@PageSize ROWS
    FETCH NEXT @PageSize ROWS ONLY
127
James Moberg

ジェームスモーバーグの答え に基づく:

SQL Server 2012がなく、OFFSETを使用できない場合、これはRow_Number()を使用する代替手段です

DECLARE 
    @PageNumEnd INT = 10, 
    @PageNum  INT = 1;

WITH TempResult AS(
    SELECT ID, NAME
    FROM Tabla
), TempCount AS (
    SELECT COUNT(*) AS MaxRows FROM TempResult
)

select * 
from
(
    SELECT
     ROW_NUMBER() OVER ( ORDER BY PolizaId DESC) AS 'NumeroRenglon', 
     MaxRows, 
     ID,
     Name
    FROM TempResult, TempCount

)resultados
WHERE   NumeroRenglon >= @PageNum
    AND NumeroRenglon <= @PageNumEnd
ORDER BY NumeroRenglon
1
elblogdelbeto