it-swarm.com.de

Abrufen der Gesamtzeilenzahl von OFFSET / FETCH NEXT

Ich habe also eine Funktion, die eine Reihe von Datensätzen zurückgibt, für die ich Paging auf meiner Website implementieren möchte. Zu diesem Zweck wurde mir vorgeschlagen, in SQL Server 2012 den Befehl "Offset/Fetch Next" zu verwenden. Auf unserer Website finden Sie einen Bereich, in dem die Gesamtzahl der Datensätze und die Seite, auf der Sie sich gerade befinden, aufgeführt sind.

Früher habe ich den gesamten Datensatz abgerufen und konnte das Paging programmgesteuert darauf aufbauen. Bei Verwendung der SQL-Methode mit FETCH NEXT X ROWS ONLY (NUR NÄCHSTE X REIHEN ABRUFEN) werden mir jedoch nur X Zeilen zurückgegeben, sodass ich nicht weiß, wie meine gesamte Datensatzmenge lautet und wie meine minimalen und maximalen Seiten berechnet werden. Die einzige Möglichkeit, dies zu tun, besteht darin, die Funktion zweimal aufzurufen und die ersten Zeilen zu zählen und dann die zweite mit FETCH NEXT auszuführen. Gibt es eine bessere Möglichkeit, bei der ich die Abfrage nicht zweimal ausführen muss? Ich versuche, die Leistung zu beschleunigen, nicht zu verlangsamen.

77
CrystalBlue

Sie können COUNT(*) OVER() ... hier ein kurzes Beispiel mit 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;

Dies sollte jedoch für kleine Datenmengen reserviert werden. Bei größeren Geräten kann die Leistung miserabel sein. Bessere Alternativen finden Sie in diesem Artikel von Paul White , einschließlich der Verwaltung indizierter Ansichten (dies funktioniert nur, wenn das Ergebnis ungefiltert ist oder Sie die WHERE -Klauseln im Voraus kennen) und Verwendung von ROW_NUMBER() Tricks.

99
Aaron Bertrand

Bei der Verwendung der COUNT () OVER () -Methode sind einige Leistungsprobleme aufgetreten. (Ich bin nicht sicher, ob es sich um den Server handelt, da es 40 Sekunden gedauert hat, bis 10 Datensätze zurückgegeben wurden und später keine Probleme aufgetreten sind.) Diese Technik hat unter allen Bedingungen funktioniert, ohne dass COUNT () OVER () verwendet werden muss, und führt dasselbe aus:

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

Basierend auf James Mobergs Antwort :

Dies ist eine Alternative mit Row_Number(), wenn Sie nicht über SQL Server 2012 verfügen und OFFSET nicht verwenden können

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