SELECT dan WHERE

Menyaring baris dengan SELECT, WHERE, dan operator perbandingannya.

Daftar isi

Topik ini membahas pernyataan SELECT beserta klausa WHERE, yaitu dua bagian query (perintah pembacaan data) yang menentukan kolom mana yang tampil dan baris mana yang lolos. Seluruh contoh berjalan pada satu tabel perpustakaan kecil yang juga dipakai topik-topik lain pada modul ini, sehingga setiap keluaran dapat dihitung ulang di terminal. Setelah membaca, penyaringan baris dengan operator perbandingan, penggabungan syarat dengan AND, OR, dan NOT, serta penyaringan dengan IN dan BETWEEN dapat ditulis dengan benar.

Dataset perpustakaan#

Seluruh contoh pada modul ini menggunakan tabel buku berisi tujuh baris dengan kolom id, judul, pengarang, tahun, dan stok. Kolom id bertipe INTEGER PRIMARY KEY sehingga berfungsi sebagai pengenal unik setiap baris. Judul Dasar Algoritma dan Peta Langit masing-masing dimiliki dua baris dengan tahun atau stok yang berbeda, dan duplikasi itu sengaja dipertahankan sebagai bahan latihan DISTINCT. Jalankan blok berikut untuk membangun tabel latihan tersebut.

sql Pembuatan tabel buku
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 * FROM buku;
text Keluaran
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

Bintang pada SELECT * berarti semua kolom, sehingga keluarannya memuat lima kolom sesuai urutan definisi tabel. Untuk menjalankan blok serupa, simpan pernyataannya sebagai berkas .sql lalu jalankan sqlite3 :memory: < nama-berkas.sql, atau tempel pernyataannya langsung pada sesi sqlite3 interaktif. Blok-blok berikutnya membangun ulang tabel yang sama secara ringkas sebelum query-nya, sehingga setiap blok tetap mandiri dan dapat dieksekusi sendiri. Tabel kecil seperti ini membuat setiap angka pada keluaran dapat diperiksa dengan mata tanpa alat bantu.

Memilih kolom dengan proyeksi#

Daftar kolom yang ditulis setelah kata SELECT menentukan proyeksi (projection), yaitu pemilihan kolom yang tampil pada hasil. Jalankan query berikut dan bandingkan dengan keluaran SELECT * sebelumnya, karena hanya judul dan pengarang yang muncul kini.

sql Memilih dua kolom
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, pengarang FROM buku;
text Keluaran
Dasar Algoritma|Ali
Peta Langit|Budi
Dasar Algoritma|Citra
Sejarah Kertas|Dewi
Kode dan Sandi|Eka
Jejak Angin|Farhan
Peta Langit|Budi

Urutan kolom pada hasil mengikuti urutan pada daftar SELECT, bukan urutan definisi tabel. Jumlah baris tidak berubah karena proyeksi hanya memilih kolom, sedangkan penyaringan baris adalah tugas WHERE. Daftar ini juga boleh memuat ekspresi perhitungan, bukan hanya nama kolom, dan kolom yang sama boleh ditulis lebih dari sekali.

Proyeksi juga menjadi cara sederhana membatasi lebar keluaran pada terminal yang sempit. Kolom yang tidak relevan bagi pertanyaan tidak ikut terbawa, sehingga hasilnya lebih ramping dan lebih mudah dibaca. Kebiasaan menuliskan daftar kolom sejak awal juga mempermudah pembacaan kembali, karena maksud query terbaca dari daftar tersebut tanpa membuka schema tabelnya. Untuk tabel yang kolomnya banyak, SELECT * menghasilkan keluaran yang melebar, sedangkan proyeksi eksplisit menyisakan yang diperlukan saja.

Menyaring baris dengan WHERE#

Klausa WHERE ditulis setelah FROM dan memuat satu ekspresi kondisi. SQLite menilai ekspresi tersebut untuk setiap baris satu per satu, dan hanya baris yang hasilnya TRUE yang diteruskan ke hasil. Enam operator perbandingan berikut tersedia untuk menyusun kondisi tersebut.

OperatorArti
=sama dengan
<>, !=tidak sama dengan
<lebih kecil
>lebih besar
<=lebih kecil atau sama dengan
>=lebih besar atau sama dengan

Jalankan query berikut untuk mengambil seluruh buku dengan stok minimal tiga.

sql Menyaring stok minimal tiga
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, stok FROM buku WHERE stok >= 3;
text Keluaran
Dasar Algoritma|4
Sejarah Kertas|3
Kode dan Sandi|5
Peta Langit|7

Empat baris lolos karena stoknya 4, 3, 5, dan 7, sedangkan tiga baris lain tersaring. Bentuk != juga sah untuk menyatakan ketidaksamaan, meskipun <> merupakan bentuk yang ditetapkan standar SQL. Query berikut memperagakan operator itu pada kolom tahun.

sql Menyaring tahun selain 2019
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 WHERE tahun <> 2019;
text Keluaran
Peta Langit|2021
Dasar Algoritma|2021
Kode dan Sandi|2023
Jejak Angin|2020
Peta Langit|2024

Lima baris yang tersisa seluruhnya berasal dari tabel yang sama, hanya kondisinya yang berbeda. Perilaku per-baris ini berlaku untuk setiap operator pada tabel di atas, tanpa kecuali. Kolom yang dibandingkan tidak harus berupa angka, karena perbandingan teks dan tanggal juga memakai operator yang sama.

Penyaringan sebelum proyeksi#

Query berikut memakai kolom stok untuk menyaring, tetapi stok tidak ikut ditampilkan pada hasilnya. Jalankan dan amati bahwa hanya judul yang tampil.

sql Kolom penyaring tidak harus ditampilkan
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 WHERE stok >= 3;
text Keluaran
Dasar Algoritma
Sejarah Kertas
Kode dan Sandi
Peta Langit

Keluaran ini memuat empat judul yang sama dengan contoh stok minimal tiga sebelumnya, hanya lebih ramping karena proyeksinya satu kolom. Hal ini memperlihatkan urutan evaluasi pada pernyataan SELECT. SQLite terlebih dahulu menilai kondisi WHERE terhadap setiap baris tabel, baru kemudian menyusun kolom hasil untuk baris yang lolos. Karena penyaringan berlangsung sebelum proyeksi, kolom stok boleh dirujuk pada WHERE meskipun tidak ada pada daftar SELECT. Sebaliknya, kolom hasil yang baru tersusun pada tahap proyeksi, misalnya ekspresi berlabel, belum tersedia untuk dirujuk pada WHERE. Dua tahap yang jelas ini membuat perilaku query mudah ditebak, yaitu penyaringan menentukan baris mana yang diproses, sedangkan proyeksi menentukan kolom mana yang ditampilkan. Diagram berikut merangkum alurnya.

FROM bukuseluruh baris tersediaWHEREsaring per barisSELECTproyeksi kolom
Urutan evaluasi pada SELECT dengan WHERE, penyaringan berlangsung sebelum proyeksi

Menggabungkan syarat dengan AND, OR, dan NOT#

Syarat yang kompleks disusun dari beberapa perbandingan yang diikat operator logika. AND menghasilkan TRUE hanya bila kedua sisinya TRUE, OR menghasilkan TRUE bila salah satu sisinya TRUE, dan NOT membalik nilai kebenaran sisinya. Jalankan query berikut untuk mengambil buku terbitan 2019 atau 2021.

sql Tahun 2019 atau 2021
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, stok FROM buku WHERE tahun = 2019 OR tahun = 2021;
text Keluaran
Dasar Algoritma|2019|4
Peta Langit|2021|0
Dasar Algoritma|2021|2
Sejarah Kertas|2019|3

Empat baris memenuhi salah satu dari dua tahun tersebut. NOT mengambil kebalikan dari keseluruhan syarat di dalam tanda kurungnya, sehingga query berikut mengambil semua tahun di luar 2019 dan 2021.

sql Tahun di luar 2019 dan 2021
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 WHERE NOT (tahun = 2019 OR tahun = 2021);
text Keluaran
Kode dan Sandi|2023
Jejak Angin|2020
Peta Langit|2024

Tiga baris yang tersisa adalah komplemen dari empat baris pada contoh OR, karena seluruh tujuh baris terbagi dua habis oleh syarat itu. Tanda kurung pada NOT wajib dipertahankan, sebab tanpa kurung NOT hanya berlaku pada ekspresi terdekatnya dan maksud query berubah.

Urutan penulisan syarat pada AND tidak memengaruhi hasil, karena SQLite menilai seluruh perbandingannya untuk setiap baris. Meskipun begitu, menyusun syarat dari yang paling menentukan sering membantu keterbacaan. Operator NOT juga dapat dipasang langsung pada satu perbandingan, misalnya NOT tahun = 2019, tetapi bentuk tanda kurung yang dipakai di atas menyatakan cakupan pembalikannya secara eksplisit dan jauh lebih mudah dibaca.

IN dan BETWEEN#

IN menyaring sebuah kolom terhadap daftar nilai, dan hasilnya sama dengan deret OR pada kolom yang bersangkutan, hanya lebih ringkas untuk dibaca. Jalankan query berikut untuk mengambil buku milik pengarang Ali atau Dewi.

sql Pengarang Ali atau Dewi
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, pengarang FROM buku WHERE pengarang IN ('Ali', 'Dewi');
text Keluaran
Dasar Algoritma|Ali
Sejarah Kertas|Dewi

BETWEEN menyaring rentang nilai dan bersifat inklusif pada kedua batasnya, sehingga x BETWEEN a AND b setara dengan x >= a AND x <= b. Blok berikut membangun tabel peminjaman berisi enam baris, lalu mengambil peminjaman pada rentang tanggal tertentu.

sql Peminjaman pada rentang tanggal
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 nama, tanggal_pinjam FROM peminjaman
  WHERE tanggal_pinjam BETWEEN '2026-03-03' AND '2026-03-10';
text Keluaran
Budi|2026-03-03
Citra|2026-03-03
Dewi|2026-03-07
Eka|2026-03-10

Batas bawah 2026-03-03 dan batas atas 2026-03-10 sama-sama ikut terpilih, bukti sifat inklusif BETWEEN. Rentang tanggal berhasil dibandingkan karena tanggal ditulis dalam format ISO yang tersusun rapi secara urutan kamus, sehingga perbandingan teksnya sejalan dengan perbandingan waktunya. Bentuk NOT IN dan NOT BETWEEN juga tersedia bila kebalikan syaratnya yang dibutuhkan.

Daftar pada IN boleh memuat puluhan nilai bila diperlukan, dan setiap nilai teks ditulis dengan tanda kutip. BETWEEN pada kolom angka bekerja dengan cara yang sama seperti pada tanggal, misalnya tahun BETWEEN 2019 AND 2021 mengambil seluruh terbitan rentang itu termasuk ujungnya. Perlu diingat bahwa urutan batasnya tidak boleh terbalik, karena BETWEEN 2023 AND 2020 tidak menemukan satu baris pun.

Kesalahan umum#

Kesalahan yang paling sering terjadi adalah mengira OR dan AND dinilai dari kiri ke kanan dengan bobot yang setara. Sebenarnya AND mengikat lebih kuat daripada OR, sehingga syarat tanpa tanda kurung terbaca berbeda dari maksud penulisnya. Amati keluaran query berikut yang ditulis tanpa tanda kurung.

sql Syarat tanpa tanda kurung
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
  WHERE tahun = 2019 OR judul = 'Peta Langit' AND tahun > 2020;
text Keluaran
Dasar Algoritma|2019
Peta Langit|2021
Sejarah Kertas|2019
Peta Langit|2024

Maksudnya adalah buku terbitan 2019 atau berjudul Peta Langit, dengan syarat tahun terbitnya di atas 2020. SQLite membacanya sebagai tahun = 2019 OR (judul = 'Peta Langit' AND tahun > 2020), sehingga kedua buku terbitan 2019 lolos meskipun tahunnya tidak di atas 2020. Perbaikannya adalah menegaskan maksud dengan tanda kurung.

sql Syarat dengan tanda kurung yang benar
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
  WHERE (tahun = 2019 OR judul = 'Peta Langit') AND tahun > 2020;
text Keluaran
Peta Langit|2021
Peta Langit|2024

Dua buku terbitan 2019 kini tersaring, dan hanya Peta Langit yang memenuhi syarat tahunnya yang tampil. Bandingkan kedua keluaran itu baris demi baris untuk melihat pengaruh tanda kurung, karena perbedaannya hanya dua baris tetapi maknanya besar. Kebiasaan yang disarankan adalah selalu memberi tanda kurung pada gabungan AND dan OR meskipun aturan prioritasnya sudah dihafal, karena tanda kurung menyatakan maksud secara eksplisit bagi pembaca query berikutnya.

Ringkasan#

  • SELECT menentukan proyeksi kolom, sedangkan WHERE menyaring baris per baris dan dievaluasi sebelum proyeksi dilakukan.
  • Enam operator perbandingan bekerja pada setiap baris, dan hanya hasil TRUE yang diteruskan ke hasil.
  • AND mengikat lebih kuat daripada OR, sehingga gabungan keduanya wajib diberi tanda kurung.
  • IN menggantikan deret OR pada satu kolom, sedangkan BETWEEN bersifat inklusif pada kedua batasnya.

Referensi#