sql >> Databáze >  >> RDS >> Sqlserver

Stránkování v SQL Server pomocí OFFSET/FETCH

Stránkování se často používá v aplikacích, kde uživatel může kliknout na Předchozí /Další můžete procházet stránkami, které tvoří výsledky, nebo kliknutím na číslo stránky přejít přímo na konkrétní stránku.

Při spouštění dotazů na serveru SQL Server můžete stránkovat výsledky pomocí OFFSET a FETCH argumenty ORDER BY doložka. Tyto argumenty byly zavedeny v SQL Server 2012, proto můžete tuto techniku ​​použít, pokud máte SQL Server 2012 nebo vyšší.

V tomto kontextu je stránkování místo, kde rozdělíte výsledky dotazu na menší části, přičemž každá část pokračuje tam, kde skončila předchozí. Pokud například dotaz vrátí 1000 řádků, můžete je stránkovat tak, aby byly vráceny ve skupinách po 100. Aplikace může SQL Serveru předat číslo stránky a velikost stránky a SQL Server ji pak může použít k vrácení pouze data pro požadovanou stránku.

Příklad 1 – Bez stránkování

Nejprve spusťte dotaz, který vrátí všechny řádky v tabulce:

SELECT *
FROM Genres
ORDER BY GenreId;

Výsledek:

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

Tento příklad nepoužívá stránkování – zobrazí se všechny výsledky.

Tato sada výsledků je tak malá, že by normálně nevyžadovala stránkování, ale pro účely tohoto článku ji pojďme stránkovat.

Příklad 2 – Zobrazení prvních 3 výsledků

Tento příklad zobrazuje první tři výsledky:

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

Výsledek:

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

V tomto případě specifikuji, že výsledky by měly začínat prvním výsledkem a zobrazovat další tři řádky. To se provádí pomocí následujícího:

  • OFFSET 0 ROWS určuje, že by neměl být žádný posun (nulový posun).
  • FETCH NEXT 3 ROWS ONLY získá další tři řádky od offsetu. Protože jsem zadal offset nula, načtou se první tři řádky.

Pokud bychom chtěli pouze 3 nejlepší výsledky, mohli bychom dosáhnout stejného výsledku pomocí TOP klauzule místo určení hodnot posunu a načtení. To by nám však neumožnilo udělat další část.

Příklad 3 – Zobrazení dalších 3 výsledků

Nyní si ukážeme následující tři výsledky:

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

Výsledek:

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

Takže jediná věc, kterou jsem změnil, byl offset.

Hodnoty offsetu a načítání mohou být také výrazy poskytnuté jako poddotaz proměnné, parametru nebo konstantního skalárního dotazu. Když je použit poddotaz, nemůže odkazovat na žádné sloupce definované ve vnějším rozsahu dotazu (nelze jej korelovat s vnějším dotazem).

Následující příklady používají výrazy, které ukazují dva přístupy k stránkování výsledků.

Příklad 4 – Stránkování podle čísla řádku

Tento příklad používá výrazy k určení řádku číslo pro začátek.

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

Výsledek:

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

Zde používám @StartRow int = 1 určit, že výsledky by měly začínat na prvním řádku.

Zde je to, co se stane, když tuto hodnotu zvýším na 2 .

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

Výsledek:

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

Začíná ve druhé řadě. Pomocí této metody mohu určit přesný řádek, na kterém má začít.

Příklad 5 – Stránkování podle čísla stránky

Tento příklad je téměř totožný s předchozím příkladem, kromě toho, že umožňuje zadat číslo stránky, nikoli číslo řádku.

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

Výsledek:

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

Takže první výsledek je stejný. Podívejme se však, co se stane, když zvýšíme @PageNumber2 (Tuto proměnnou jsem přejmenoval, aby odrážela její nový účel).

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

Výsledek:

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

Tentokrát výsledky začínají na čtvrté řadě. Takže pomocí této metody můžete jednoduše předat číslo stránky místo čísla řádku.

Příklad 6 – Smyčka stránkování

Na závěr uvádíme rychlý příklad, který prochází všechny stránky a udává číslo počátečního řádku pro každou iteraci:

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;

Výsledek:

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

Příklad 7 – ROW vs. ROWS

Pokud narazíte na kód, který používá ROW místo ROWS , oba argumenty dělají totéž. Jsou to synonyma a jsou poskytovány pro kompatibilitu s ANSI.

Zde je první příklad na této stránce, ale s ROW místo ROWS .

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

Výsledek:

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

Příklad 8 – PRVNÍ vs. DALŠÍ

Totéž platí pro FIRST a NEXT . Toto jsou synonyma poskytovaná pro kompatibilitu ANSI.

Zde je předchozí příklad, ale s FIRST místo NEXT .

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

Výsledek:

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

  1. Jak můžeme definovat velikost výstupního parametru v uložené proceduře?

  2. Příklady TIMESTAMPADD() – MySQL

  3. Jak použít smyčku SQL for k vložení řádků do databáze?

  4. Jak vložit časové razítko do Oracle?