sql >> Database >  >> RDS >> Sqlserver

Paginering in SQL Server met OFFSET/FETCH

Paginering wordt vaak gebruikt in toepassingen waar de gebruiker kan klikken op Vorige /Volgende om door de pagina's te navigeren die deel uitmaken van de resultaten, of klik op een paginanummer om direct naar een specifieke pagina te gaan.

Wanneer u query's uitvoert in SQL Server, kunt u de resultaten pagineren met behulp van de OFFSET en FETCH argumenten van de ORDER BY clausule. Deze argumenten zijn geïntroduceerd in SQL Server 2012, daarom kunt u deze techniek gebruiken als u SQL Server 2012 of hoger hebt.

In deze context is paginering de plaats waar u de queryresultaten in kleinere stukken verdeelt, waarbij elk stuk verdergaat waar het vorige eindigde. Als een query bijvoorbeeld 1000 rijen retourneert, kunt u ze pagineren zodat ze worden geretourneerd in groepen van 100. Een toepassing kan het paginanummer en de paginagrootte doorgeven aan SQL Server, en SQL Server kan deze vervolgens gebruiken om alleen de gegevens voor de opgevraagde pagina.

Voorbeeld 1 – Geen paginering

Laten we eerst een query uitvoeren die alle rijen in een tabel retourneert:

SELECT *
FROM Genres
ORDER BY GenreId;

Resultaat:

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

Dit voorbeeld gebruikt geen paginering - alle resultaten worden weergegeven.

Deze resultatenset is zo klein dat paginering normaal gesproken niet nodig is, maar laten we hem voor de doeleinden van dit artikel pagineren.

Voorbeeld 2 – Toon de eerste 3 resultaten

In dit voorbeeld worden de eerste drie resultaten weergegeven:

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

Resultaat:

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

In dit geval specificeer ik dat de resultaten moeten beginnen bij het eerste resultaat en de volgende drie rijen moeten weergeven. Dit wordt gedaan met behulp van het volgende:

  • OFFSET 0 ROWS specificeert dat er geen offset mag zijn (een offset van nul).
  • FETCH NEXT 3 ROWS ONLY krijgt de volgende drie rijen van de offset. Aangezien ik een offset van nul heb opgegeven, worden de eerste drie rijen opgehaald.

Als we alleen de top 3 resultaten wilden, hadden we hetzelfde resultaat kunnen bereiken door de TOP te gebruiken. clausule in plaats van de offset- en fetch-waarden op te geven. Dit zou ons echter niet in staat hebben gesteld om het volgende deel te doen.

Voorbeeld 3 – Toon de volgende 3 resultaten

Laten we nu de volgende drie resultaten weergeven:

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

Resultaat:

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

Dus het enige dat ik veranderde was de offset.

De offset- en ophaalwaarden kunnen ook een uitdrukking zijn die wordt geleverd als een variabele, parameter of constante scalaire subquery. Wanneer een subquery wordt gebruikt, kan deze niet verwijzen naar kolommen die zijn gedefinieerd in het buitenste querybereik (deze kan niet worden gecorreleerd met de buitenste query).

In de volgende voorbeelden worden expressies gebruikt om twee benaderingen te tonen voor het pagineren van de resultaten.

Voorbeeld 4 – Paginering op rijnummer

In dit voorbeeld worden expressies gebruikt om de rij . te specificeren nummer om mee te beginnen.

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

Resultaat:

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

Hier gebruik ik @StartRow int = 1 om aan te geven dat de resultaten op de eerste rij moeten beginnen.

Dit is wat er gebeurt als ik die waarde verhoog naar 2 .

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

Resultaat:

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

Het begint op de tweede rij. Met deze methode kan ik de exacte rij specificeren om mee te beginnen.

Voorbeeld 5 – Paginering op paginanummer

Dit voorbeeld is bijna identiek aan het vorige voorbeeld, behalve dat u het paginanummer kunt specificeren, in plaats van het rijnummer.

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

Resultaat:

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

Het eerste resultaat is dus hetzelfde. Laten we echter eens kijken wat er gebeurt als we @PageNumber . verhogen tot 2 (Ik heb deze variabele hernoemd om het nieuwe doel weer te geven).

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

Resultaat:

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

Deze keer beginnen de resultaten op de vierde rij. Met deze methode kunt u dus eenvoudig het paginanummer doorgeven in plaats van het rijnummer.

Voorbeeld 6 – Pagineringslus

Om af te ronden, hier is een snel voorbeeld dat door alle pagina's loopt en het startrijnummer voor elke iteratie specificeert:

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;

Resultaat:

+-----------+---------+
| 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)

Voorbeeld 7 – RIJ versus RIJEN

Als u code tegenkomt die gebruikmaakt van ROW in plaats van ROWS , doen beide argumenten hetzelfde. Het zijn synoniemen en zijn bedoeld voor ANSI-compatibiliteit.

Hier is het eerste voorbeeld op deze pagina, maar met ROW in plaats van ROWS .

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

Resultaat:

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

Voorbeeld 8 – EERSTE vs VOLGENDE

Hetzelfde geldt voor FIRST en NEXT . Dit zijn synoniemen voor ANSI-compatibiliteit.

Hier is het vorige voorbeeld, maar met FIRST in plaats van NEXT .

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

Resultaat:

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

  1. SQL Server 2005 DateAdd gebruiken om een ​​dag aan een datum toe te voegen

  2. Welke maat gebruikt u voor varchar(MAX) in uw parameterdeclaratie?

  3. Oracle PL/SQL:controleren of BLOB of CLOB leeg is

  4. COS() Functie in Oracle