Topik ini membahas DISTINCT untuk membuang baris hasil yang duplikat serta LIMIT dan OFFSET untuk membatasi jumlah baris, termasuk pola paginasi halaman. Tabel latihannya adalah tabel buku perpustakaan yang sama dengan topik-topik lain pada modul ini, lengkap dengan judul kembar dan tahun kembar. Setelah membaca, duplikasi pada satu kolom maupun beberapa kolom dapat dibuang dengan tepat, dan pengambilan data per halaman dapat ditulis dengan pola yang benar.
Dataset contoh#
Tabel buku berisi tujuh baris, dan judul Dasar Algoritma serta Peta Langit masing-masing dimiliki dua baris karena terbitan yang berbeda. Blok berikut membangun ulang tabel itu lalu menampilkan kolom judul saja, agar duplikasinya terlihat jelas.
CREATE TABLE buku (id INTEGER PRIMARY KEY, judul TEXT, pengarang TEXT, tahun INTEGER, stok INTEGER);
INSERT INTO buku VALUES
(1, 'Dasar Algoritma', 'Ali', 2019, 4),
(2, 'Peta Langit', 'Budi', 2021, 0),
(3, 'Dasar Algoritma', 'Citra', 2021, 2),
(4, 'Sejarah Kertas', 'Dewi', 2019, 3),
(5, 'Kode dan Sandi', 'Eka', 2023, 5),
(6, 'Jejak Angin', 'Farhan', 2020, 0),
(7, 'Peta Langit', 'Budi', 2024, 7);
SELECT judul FROM buku;Dasar Algoritma
Peta Langit
Dasar Algoritma
Sejarah Kertas
Kode dan Sandi
Jejak Angin
Peta LangitTujuh baris menghasilkan hanya lima judul yang berbeda, karena Dasar Algoritma dan Peta Langit masing-masing tampil dua kali. Kondisi semacam ini lazim pada data nyata, misalnya daftar pengarang atau daftar kategori yang otomatis diambil dari tabel transaksi. Kata DISTINCT dipasang tepat setelah SELECT untuk menangani duplikasi tersebut.
Perhatikan bahwa dua judul yang berulang bukan salinan yang persis sama pada seluruh kolomnya, karena tahun, stok, atau pengarangnya berbeda. Yang berulang hanyalah nilai pada kolom judul, dan itulah yang terlihat ketika hanya kolom tersebut yang dipilih. Pemahaman ini penting sebelum memakai DISTINCT, karena operator itu menilai kolom-kolom yang muncul pada hasil, bukan seluruh kolom tabel yang tidak ikut dipilih. Nilai yang berulang pada satu kolom sementara kolom lainnya berbeda inilah kasus yang paling sering memancing salah tafsir.
DISTINCT pada satu kolom#
DISTINCT memerintahkan SQLite membandingkan setiap baris hasil dengan baris-baris sebelumnya, lalu membuang baris yang identik. Jalankan query berikut untuk mendapatkan daftar judul tanpa duplikasi.
CREATE TABLE buku (id INTEGER PRIMARY KEY, judul TEXT, pengarang TEXT, tahun INTEGER, stok INTEGER);
INSERT INTO buku VALUES
(1, 'Dasar Algoritma', 'Ali', 2019, 4),
(2, 'Peta Langit', 'Budi', 2021, 0),
(3, 'Dasar Algoritma', 'Citra', 2021, 2),
(4, 'Sejarah Kertas', 'Dewi', 2019, 3),
(5, 'Kode dan Sandi', 'Eka', 2023, 5),
(6, 'Jejak Angin', 'Farhan', 2020, 0),
(7, 'Peta Langit', 'Budi', 2024, 7);
SELECT DISTINCT judul FROM buku;Dasar Algoritma
Peta Langit
Sejarah Kertas
Kode dan Sandi
Jejak AnginTujuh baris menyusut menjadi lima karena setiap judul hanya tampil sekali. DISTINCT juga dapat diterapkan pada kolom angka, misalnya tahun terbit.
CREATE TABLE buku (id INTEGER PRIMARY KEY, judul TEXT, pengarang TEXT, tahun INTEGER, stok INTEGER);
INSERT INTO buku VALUES
(1, 'Dasar Algoritma', 'Ali', 2019, 4),
(2, 'Peta Langit', 'Budi', 2021, 0),
(3, 'Dasar Algoritma', 'Citra', 2021, 2),
(4, 'Sejarah Kertas', 'Dewi', 2019, 3),
(5, 'Kode dan Sandi', 'Eka', 2023, 5),
(6, 'Jejak Angin', 'Farhan', 2020, 0),
(7, 'Peta Langit', 'Budi', 2024, 7);
SELECT DISTINCT tahun FROM buku;2019
2021
2023
2020
2024Tahun 2019 dan 2021 masing-masing dimiliki dua buku, sehingga keduanya hanya tampil sekali pada keluaran ini. Perhatikan pula bahwa urutan baris pada hasil DISTINCT tidak dijamin oleh SQL. Pada contoh ini nilai tampil mengikuti urutan kemunculan pertamanya di tabel, dan penyusunan ulang tetap menjadi tugas ORDER BY bila urutan tertentu dibutuhkan.
Biaya DISTINCT membesar seiring jumlah baris, karena setiap baris hasil harus dibandingkan dengan baris-baris yang sudah lolos. Pada tabel kecil seperti contoh ini perbedaannya tidak terasa, sedangkan pada tabel puluhan ribu baris deduplikasi menjadi pekerjaan yang nyata. Karena itu DISTINCT sebaiknya dipakai hanya bila duplikasinya memang tidak diinginkan, dan bukan sekadar penambah rapi pada setiap query.
DISTINCT pada beberapa kolom#
DISTINCT bekerja pada seluruh kombinasi kolom hasil, bukan pada kolom pertama saja. Dua baris dinyatakan duplikat hanya bila nilai pada setiap kolom hasilnya sama. Query berikut menerapkannya pada pasangan judul dan tahun.
CREATE TABLE buku (id INTEGER PRIMARY KEY, judul TEXT, pengarang TEXT, tahun INTEGER, stok INTEGER);
INSERT INTO buku VALUES
(1, 'Dasar Algoritma', 'Ali', 2019, 4),
(2, 'Peta Langit', 'Budi', 2021, 0),
(3, 'Dasar Algoritma', 'Citra', 2021, 2),
(4, 'Sejarah Kertas', 'Dewi', 2019, 3),
(5, 'Kode dan Sandi', 'Eka', 2023, 5),
(6, 'Jejak Angin', 'Farhan', 2020, 0),
(7, 'Peta Langit', 'Budi', 2024, 7);
SELECT DISTINCT judul, tahun FROM buku;Dasar Algoritma|2019
Peta Langit|2021
Dasar Algoritma|2021
Sejarah Kertas|2019
Kode dan Sandi|2023
Jejak Angin|2020
Peta Langit|2024Tujuh baris tetap ada, berbeda dari hasil DISTINCT judul yang hanya lima. Penyebabnya adalah baris Peta Langit 2021 dan Peta Langit 2024, yang saling berbeda pada kolom tahun sehingga keduanya tetap dihitung sebagai kombinasi unik. Perbandingan kedua keluaran itu menjadi bukti bahwa DISTINCT menilai baris hasil secara utuh. Perlu diingat pula dua kasus khususnya, yaitu perbandingan teks yang peka huruf sehingga dua penulisan yang berbeda hurufnya dianggap dua nilai, serta kombinasi yang sama-sama kosong karena NULL pada DISTINCT diperlakukan saling setara dan tergabung menjadi satu. Contoh berikut menerapkannya pada tabel peminjaman yang berisi tanggal kembar.
CREATE TABLE peminjaman (
id INTEGER PRIMARY KEY,
nama TEXT,
buku_id INTEGER,
tanggal_pinjam TEXT
);
INSERT INTO peminjaman VALUES
(1, 'Ali', 1, '2026-03-01'),
(2, 'Budi', 2, '2026-03-03'),
(3, 'Citra', 3, '2026-03-03'),
(4, 'Dewi', 1, '2026-03-07'),
(5, 'Eka', 5, '2026-03-10'),
(6, 'Farhan', 6, '2026-03-12');
SELECT DISTINCT tanggal_pinjam FROM peminjaman;2026-03-01
2026-03-03
2026-03-07
2026-03-10
2026-03-12Enam baris peminjaman menyusut menjadi lima tanggal karena Budi dan Citra meminjam pada hari yang sama. Pola semacam ini dipakai ketika pertanyaannya berbunyi pada tanggal apa saja terjadi aktivitas, tanpa memedulikan berapa kali.
LIMIT dan OFFSET#
LIMIT membatasi jumlah baris yang dikembalikan, sedangkan OFFSET melewati sejumlah baris terlebih dahulu sebelum batas itu dihitung. Pada query paginasi, urutan baris harus ditetapkan dengan ORDER BY agar setiap eksekusi menghasilkan anggota halaman yang sama, dan contoh di sini memakai ORDER BY id. Jalankan query berikut untuk mengambil tiga baris pertama.
CREATE TABLE buku (id INTEGER PRIMARY KEY, judul TEXT, pengarang TEXT, tahun INTEGER, stok INTEGER);
INSERT INTO buku VALUES
(1, 'Dasar Algoritma', 'Ali', 2019, 4),
(2, 'Peta Langit', 'Budi', 2021, 0),
(3, 'Dasar Algoritma', 'Citra', 2021, 2),
(4, 'Sejarah Kertas', 'Dewi', 2019, 3),
(5, 'Kode dan Sandi', 'Eka', 2023, 5),
(6, 'Jejak Angin', 'Farhan', 2020, 0),
(7, 'Peta Langit', 'Budi', 2024, 7);
SELECT judul, tahun FROM buku ORDER BY id LIMIT 3;Dasar Algoritma|2019
Peta Langit|2021
Dasar Algoritma|2021Bentuk LIMIT 3 OFFSET 3 melewati tiga baris pertama, lalu mengambil tiga baris berikutnya.
CREATE TABLE buku (id INTEGER PRIMARY KEY, judul TEXT, pengarang TEXT, tahun INTEGER, stok INTEGER);
INSERT INTO buku VALUES
(1, 'Dasar Algoritma', 'Ali', 2019, 4),
(2, 'Peta Langit', 'Budi', 2021, 0),
(3, 'Dasar Algoritma', 'Citra', 2021, 2),
(4, 'Sejarah Kertas', 'Dewi', 2019, 3),
(5, 'Kode dan Sandi', 'Eka', 2023, 5),
(6, 'Jejak Angin', 'Farhan', 2020, 0),
(7, 'Peta Langit', 'Budi', 2024, 7);
SELECT judul, tahun FROM buku ORDER BY id LIMIT 3 OFFSET 3;Sejarah Kertas|2019
Kode dan Sandi|2023
Jejak Angin|2020Halaman ketiga memakai OFFSET 6 dan hanya menyisakan satu baris, karena tabel ini berisi tujuh baris.
CREATE TABLE buku (id INTEGER PRIMARY KEY, judul TEXT, pengarang TEXT, tahun INTEGER, stok INTEGER);
INSERT INTO buku VALUES
(1, 'Dasar Algoritma', 'Ali', 2019, 4),
(2, 'Peta Langit', 'Budi', 2021, 0),
(3, 'Dasar Algoritma', 'Citra', 2021, 2),
(4, 'Sejarah Kertas', 'Dewi', 2019, 3),
(5, 'Kode dan Sandi', 'Eka', 2023, 5),
(6, 'Jejak Angin', 'Farhan', 2020, 0),
(7, 'Peta Langit', 'Budi', 2024, 7);
SELECT judul, tahun FROM buku ORDER BY id LIMIT 3 OFFSET 6;Peta Langit|2024Ketiga query tersebut membentuk pola paginasi yang lengkap. Halaman ke-p dengan ukuran k ditulis LIMIT k OFFSET (p-1)*k, sehingga halaman 1 memakai OFFSET 0, halaman 2 memakai OFFSET 3, dan halaman 3 memakai OFFSET 6 pada contoh ini. Halaman terakhir yang kurang dari k baris tetap sah, sebagaimana keluaran satu baris di atas. Tanpa ORDER BY, LIMIT tetap berjalan tetapi anggota halamannya tidak dapat diandalkan, karena urutan baris pada dasar penyaringan tidak dijamin. Karena itu kebiasaan yang benar adalah memasangkan setiap LIMIT halaman dengan ORDER BY yang stabil, misalnya kolom id atau kolom tanggal yang unik.
Kesalahan umum#
Kesalahan yang lazim terjadi pada paginasi adalah mengira halaman pertama dimulai dari OFFSET 1. Faktanya OFFSET menghitung dari nol, sehingga OFFSET 1 justru melewatkan baris pertama. Amati query berikut yang hendak mengambil halaman pertama tetapi salah menulis OFFSET-nya.
CREATE TABLE buku (id INTEGER PRIMARY KEY, judul TEXT, pengarang TEXT, tahun INTEGER, stok INTEGER);
INSERT INTO buku VALUES
(1, 'Dasar Algoritma', 'Ali', 2019, 4),
(2, 'Peta Langit', 'Budi', 2021, 0),
(3, 'Dasar Algoritma', 'Citra', 2021, 2),
(4, 'Sejarah Kertas', 'Dewi', 2019, 3),
(5, 'Kode dan Sandi', 'Eka', 2023, 5),
(6, 'Jejak Angin', 'Farhan', 2020, 0),
(7, 'Peta Langit', 'Budi', 2024, 7);
SELECT judul FROM buku ORDER BY id LIMIT 3 OFFSET 1;Peta Langit
Dasar Algoritma
Sejarah KertasBaris pertama bernama Dasar Algoritma hilang, dan halaman ini justru menampilkan tiga baris yang seharusnya menjadi bagian awal halaman kedua. Perbaikannya adalah menulis OFFSET 0 untuk halaman pertama, atau menghilangkan OFFSET sepenuhnya karena LIMIT 3 saja sudah setara. Kesalahan kedua yang sering menyertai adalah LIMIT tanpa ORDER BY, yang membuat anggota halaman dapat berubah antareksekusi karena urutan barisnya tidak dijamin.
Kesalahan ketiga menyangkut DISTINCT, yaitu menggabungkannya dengan kolom yang nilainya unik. Menambahkan kolom id pada daftar hasil membuat setiap baris berbeda dari yang lain, sehingga SELECT DISTINCT id, judul FROM buku tetap mengembalikan tujuh baris dan kesannya seolah-olah DISTINCT tidak bekerja. Aturan kombinasi kolom pada DISTINCT menjelaskan penyebabnya, dan perbaikannya adalah memasukkan hanya kolom yang memang hendak dideduplikasi.
Ringkasan#
- DISTINCT membandingkan seluruh kombinasi kolom hasil, sehingga baris yang berbeda pada salah satu kolomnya tetap tampil.
- LIMIT membatasi jumlah baris, sedangkan OFFSET melewati baris dari posisi nol sebelum batas itu berlaku.
- Halaman ke-p berukuran k ditulis
LIMIT k OFFSET (p-1)*kdan wajib disertai ORDER BY agar anggota halamannya tetap. - DISTINCT mengembalikan keluaran yang urutannya tidak dijamin, sehingga penyusunan ulang tetap menjadi tugas ORDER BY.
Referensi#
- SELECT — Dokumentasi SQLite — Semantik DISTINCT, LIMIT, dan OFFSET pada pernyataan SELECT.