Pagination sering digunakan dalam aplikasi di mana pengguna dapat mengklik Sebelumnya /Selanjutnya untuk menavigasi halaman yang membentuk hasil, atau klik nomor halaman untuk langsung membuka halaman tertentu.
Saat menjalankan kueri di SQL Server, Anda dapat membuat paginasi hasilnya dengan menggunakan OFFSET
dan FETCH
argumen dari ORDER BY
ayat. Argumen ini diperkenalkan di SQL Server 2012, oleh karena itu Anda dapat menggunakan teknik ini jika Anda memiliki SQL Server 2012 atau lebih tinggi.
Dalam konteks ini, pagination adalah tempat Anda membagi hasil kueri menjadi potongan-potongan yang lebih kecil, setiap potongan melanjutkan di mana yang sebelumnya selesai. Misalnya, jika kueri mengembalikan 1000 baris, Anda dapat membuat paginasinya sehingga dikembalikan dalam kelompok 100. Aplikasi dapat meneruskan nomor halaman dan ukuran halaman ke SQL Server, dan SQL Server kemudian dapat menggunakannya untuk mengembalikan hanya data untuk halaman yang diminta.
Contoh 1 – Tanpa Pagination
Pertama, mari kita jalankan kueri yang mengembalikan semua baris dalam tabel:
SELECT * FROM Genres ORDER BY GenreId;
Hasil:
+-----------+---------+ | GenreId | Genre | |-----------+---------| | 1 | Rock | | 2 | Jazz | | 3 | Country | | 4 | Pop | | 5 | Blues | | 6 | Hip Hop | | 7 | Rap | | 8 | Punk | +-----------+---------+
Contoh ini tidak menggunakan pagination – semua hasil ditampilkan.
Kumpulan hasil ini sangat kecil sehingga biasanya tidak memerlukan pagination, tetapi untuk tujuan artikel ini, mari kita membuat paginasi.
Contoh 2 – Menampilkan 3 Hasil Pertama
Contoh ini menampilkan tiga hasil pertama:
SELECT * FROM Genres ORDER BY GenreId OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY;
Hasil:
+-----------+---------+ | GenreId | Genre | |-----------+---------| | 1 | Rock | | 2 | Jazz | | 3 | Country | +-----------+---------+
Dalam hal ini, saya menentukan bahwa hasil harus dimulai dari hasil pertama dan menampilkan tiga baris berikutnya. Ini dilakukan dengan menggunakan yang berikut ini:
OFFSET 0 ROWS
menentukan bahwa tidak boleh ada offset (offset nol).FETCH NEXT 3 ROWS ONLY
mendapat tiga baris berikutnya dari offset. Karena saya menetapkan offset nol, tiga baris pertama diambil.
Jika yang kami inginkan hanyalah 3 hasil teratas, kami dapat mencapai hasil yang sama dengan menggunakan TOP
klausa alih-alih menentukan nilai offset dan fetch. Namun, ini tidak memungkinkan kami untuk melakukan bagian selanjutnya.
Contoh 3 – Menampilkan 3 Hasil Selanjutnya
Sekarang mari kita tampilkan tiga hasil berikutnya:
SELECT * FROM Genres ORDER BY GenreId OFFSET 3 ROWS FETCH NEXT 3 ROWS ONLY;
Hasil:
+-----------+---------+ | GenreId | Genre | |-----------+---------| | 4 | Pop | | 5 | Blues | | 6 | Hip Hop | +-----------+---------+
Jadi satu-satunya yang saya ubah adalah offsetnya.
Nilai offset dan pengambilan juga dapat berupa ekspresi yang disediakan sebagai variabel, parameter, atau subkueri skalar konstan. Saat subkueri digunakan, subkueri tidak dapat mereferensikan kolom apa pun yang ditentukan dalam cakupan kueri luar (tidak dapat dikorelasikan dengan kueri luar).
Contoh berikut menggunakan ekspresi untuk menunjukkan dua pendekatan untuk membuat halaman hasil.
Contoh 4 – Paginasi dengan Nomor Baris
Contoh ini menggunakan ekspresi untuk menentukan baris nomor untuk memulai.
DECLARE @StartRow int = 1, @RowsPerPage int = 3; SELECT * FROM Genres ORDER BY GenreId ASC OFFSET @StartRow - 1 ROWS FETCH NEXT @RowsPerPage ROWS ONLY;
Hasil:
+-----------+---------+ | GenreId | Genre | |-----------+---------| | 1 | Rock | | 2 | Jazz | | 3 | Country | +-----------+---------+
Di sini, saya menggunakan @StartRow int = 1
untuk menentukan bahwa hasil harus dimulai dari baris pertama.
Inilah yang terjadi jika saya menaikkan nilai itu menjadi 2
.
DECLARE @StartRow int = 2, @RowsPerPage int = 3; SELECT * FROM Genres ORDER BY GenreId ASC OFFSET @StartRow - 1 ROWS FETCH NEXT @RowsPerPage ROWS ONLY;
Hasil:
+-----------+---------+ | GenreId | Genre | |-----------+---------| | 2 | Jazz | | 3 | Country | | 4 | Pop | +-----------+---------+
Itu dimulai dari baris kedua. Dengan menggunakan metode ini, saya dapat menentukan baris yang tepat untuk memulai.
Contoh 5 – Paginasi berdasarkan Nomor Halaman
Contoh ini hampir identik dengan contoh sebelumnya, kecuali bahwa ini memungkinkan Anda untuk menentukan nomor halaman, sebagai lawan dari nomor baris.
DECLARE @PageNumber int = 1, @RowsPerPage int = 3; SELECT * FROM Genres ORDER BY GenreId ASC OFFSET (@PageNumber - 1) * @RowsPerPage ROWS FETCH NEXT @RowsPerPage ROWS ONLY;
Hasil:
+-----------+---------+ | GenreId | Genre | |-----------+---------| | 1 | Rock | | 2 | Jazz | | 3 | Country | +-----------+---------+
Jadi hasil pertama adalah sama. Namun, mari kita lihat apa yang terjadi ketika kita menambahkan @PageNumber
ke 2
(Saya mengganti nama variabel ini untuk mencerminkan tujuan barunya).
DECLARE @PageNumber int = 2, @RowsPerPage int = 3; SELECT * FROM Genres ORDER BY GenreId ASC OFFSET (@PageNumber - 1) * @RowsPerPage ROWS FETCH NEXT @RowsPerPage ROWS ONLY;
Hasil:
+-----------+---------+ | GenreId | Genre | |-----------+---------| | 4 | Pop | | 5 | Blues | | 6 | Hip Hop | +-----------+---------+
Kali ini hasil dimulai dari baris keempat. Jadi dengan menggunakan metode ini, Anda cukup memasukkan nomor halaman daripada nomor baris.
Contoh 6 – Pengulangan Pagination
Untuk menyelesaikannya, berikut adalah contoh cepat yang mengulang semua halaman dan menentukan nomor baris awal untuk setiap iterasi:
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;
Hasil:
+-----------+---------+ | 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)
Contoh 7 – ROW vs ROWS
Jika Anda menemukan kode yang menggunakan ROW
bukannya ROWS
, kedua argumen melakukan hal yang sama. Mereka adalah sinonim dan disediakan untuk kompatibilitas ANSI.
Ini adalah contoh pertama di halaman ini, tetapi dengan ROW
bukannya ROWS
.
SELECT * FROM Genres ORDER BY GenreId OFFSET 0 ROW FETCH NEXT 3 ROW ONLY;
Hasil:
+-----------+---------+ | GenreId | Genre | |-----------+---------| | 1 | Rock | | 2 | Jazz | | 3 | Country | +-----------+---------+
Contoh 8 – PERTAMA vs BERIKUTNYA
Hal yang sama berlaku untuk FIRST
dan NEXT
. Ini adalah sinonim yang disediakan untuk kompatibilitas ANSI.
Ini contoh sebelumnya tetapi dengan FIRST
bukannya NEXT
.
SELECT * FROM Genres ORDER BY GenreId OFFSET 0 ROW FETCH FIRST 3 ROW ONLY;
Hasil:
+-----------+---------+ | GenreId | Genre | |-----------+---------| | 1 | Rock | | 2 | Jazz | | 3 | Country | +-----------+---------+