Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Phân trang trong SQL Server bằng cách sử dụng OFFSET / FETCH

Phân trang thường được sử dụng trong các ứng dụng mà người dùng có thể nhấp vào Trước đó / Tiếp theo để điều hướng các trang tạo nên kết quả hoặc nhấp vào số trang để chuyển thẳng đến một trang cụ thể.

Khi chạy các truy vấn trong SQL Server, bạn có thể phân trang kết quả bằng cách sử dụng OFFSETFETCH các đối số của ORDER BY mệnh đề. Các đối số này đã được giới thiệu trong SQL Server 2012, do đó bạn có thể sử dụng kỹ thuật này nếu bạn có SQL Server 2012 trở lên.

Trong ngữ cảnh này, phân trang là nơi bạn chia kết quả truy vấn thành các phần nhỏ hơn, mỗi phần tiếp tục ở vị trí kết thúc trước đó. Ví dụ:nếu một truy vấn trả về 1000 hàng, bạn có thể phân trang chúng để chúng được trả về theo nhóm 100. Một ứng dụng có thể chuyển số trang và kích thước trang cho SQL Server và SQL Server sau đó có thể sử dụng nó để trả về dữ liệu cho trang được yêu cầu.

Ví dụ 1 - Không phân trang

Đầu tiên, hãy chạy một truy vấn trả về tất cả các hàng trong một bảng:

SELECT *
FROM Genres
ORDER BY GenreId;

Kết quả:

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

Ví dụ này không sử dụng phân trang - tất cả các kết quả đều được hiển thị.

Tập hợp kết quả này quá nhỏ nên thông thường nó sẽ không yêu cầu phân trang, nhưng với mục đích của bài viết này, chúng ta hãy phân trang nó.

Ví dụ 2 - Hiển thị 3 kết quả đầu tiên

Ví dụ này hiển thị ba kết quả đầu tiên:

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

Kết quả:

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

Trong trường hợp này, tôi chỉ định rằng kết quả phải bắt đầu từ kết quả đầu tiên và hiển thị ba hàng tiếp theo. Điều này được thực hiện bằng cách sử dụng như sau:

  • OFFSET 0 ROWS chỉ định rằng không được bù trừ (độ lệch bằng 0).
  • FETCH NEXT 3 ROWS ONLY lấy ba hàng tiếp theo từ phần bù. Vì tôi đã chỉ định độ lệch bằng 0 nên ba hàng đầu tiên sẽ được tìm nạp.

Nếu tất cả những gì chúng tôi muốn là 3 kết quả hàng đầu, chúng tôi có thể đạt được kết quả tương tự bằng cách sử dụng TOP thay vì chỉ định giá trị bù đắp và tìm nạp. Tuy nhiên, điều này sẽ không cho phép chúng tôi làm phần tiếp theo.

Ví dụ 3 - Hiển thị 3 kết quả tiếp theo

Bây giờ, hãy hiển thị ba kết quả tiếp theo:

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

Kết quả:

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

Vì vậy, điều duy nhất tôi thay đổi là phần bù.

Các giá trị bù đắp và tìm nạp cũng có thể là một biểu thức được cung cấp dưới dạng một biến, tham số hoặc truy vấn con vô hướng hằng số. Khi một truy vấn con được sử dụng, nó không thể tham chiếu đến bất kỳ cột nào được xác định trong phạm vi truy vấn bên ngoài (nó không thể tương quan với truy vấn bên ngoài).

Các ví dụ sau đây sử dụng các biểu thức để chỉ ra hai cách tiếp cận để phân trang kết quả.

Ví dụ 4 - Phân trang theo số hàng

Ví dụ này sử dụng các biểu thức để chỉ định hàng số để bắt đầu tại.

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

Kết quả:

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

Ở đây, tôi sử dụng @StartRow int = 1 để chỉ định rằng kết quả phải bắt đầu ở hàng đầu tiên.

Đây là những gì sẽ xảy ra nếu tôi tăng giá trị đó lên 2 .

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

Kết quả:

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

Nó bắt đầu ở hàng thứ hai. Sử dụng phương pháp này, tôi có thể chỉ định hàng chính xác để bắt đầu.

Ví dụ 5 - Phân trang theo số trang

Ví dụ này gần giống với ví dụ trước, ngoại trừ việc nó cho phép bạn chỉ định số trang, trái ngược với số hàng.

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

Kết quả:

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

Vì vậy, kết quả đầu tiên là như nhau. Tuy nhiên, hãy xem điều gì sẽ xảy ra khi chúng ta tăng @PageNumber thành 2 (Tôi đã đổi tên biến này để phản ánh mục đích mới của nó).

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

Kết quả:

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

Lần này kết quả bắt đầu từ hàng thứ tư. Vì vậy, bằng cách sử dụng phương pháp này, bạn có thể chỉ cần chuyển số trang chứ không phải số hàng.

Ví dụ 6 - Vòng lặp phân trang

Để kết thúc, đây là một ví dụ nhanh lặp lại tất cả các trang và chỉ định số hàng bắt đầu cho mỗi lần lặp:

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;

Kết quả:

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

Ví dụ 7 - ROW so với ROWS

Nếu bạn gặp mã sử dụng ROW thay vì ROWS , cả hai đối số đều làm điều tương tự. Chúng là từ đồng nghĩa và được cung cấp để tương thích với ANSI.

Đây là ví dụ đầu tiên trên trang này, nhưng với ROW thay vì ROWS .

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

Kết quả:

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

Ví dụ 8 - FIRST so với NEXT

Điều tương tự cũng áp dụng cho FIRSTNEXT . Đây là những từ đồng nghĩa được cung cấp cho khả năng tương thích ANSI.

Đây là ví dụ trước nhưng với FIRST thay vì NEXT .

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

Kết quả:

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

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Làm thế nào để chèn các ký tự Ả Rập vào cơ sở dữ liệu SQL?

  2. Cập nhật SQL từ Bảng này sang Bảng khác dựa trên khớp ID

  3. Làm cách nào để tạo khóa tổng hợp với SQL Server Management Studio?

  4. Kết nối PHP với MSSQL qua PDO ODBC

  5. STRING_SPLIT () trong SQL Server 2016:Tiếp theo # 1