Idenya
SELECT memilih kolom. WHERE memilih baris. Bersama-sama keduanya mengubah "tampilkan seluruh tabel" menjadi "tampilkan pesanan app yang completed dari bulan Maret", yang merupakan bentuk pertanyaan sungguhan.
WHERE adalah tombol filter di spreadsheet. Setiap baris diuji terhadap kondisimu; baris yang lolos tetap ada, sisanya menghilang dari hasil (tidak dihapus, hanya tidak ditampilkan).
Filter pertamamu
Tabel products berisi 15 produk dari lima kategori. Kalau seorang pelanggan bertanya "kopi apa saja yang kamu jual?", kamu tidak ingin memberinya seluruh daftar lalu membiarkannya mencari sendiri. WHERE menambahkan sebuah kondisi, dan database hanya mengembalikan baris-baris yang memenuhi kondisi itu:
SELECT name, price
FROM products
WHERE category = 'Coffee';
name | price
----------------------+--------
Arabica Gayo 250g | 95000
Robusta Lampung 250g | 65000
Toraja Kalosi 250g | 110000
(3 rows)
WHEREdatang setelahFROM.- Nilai teks ditulis dalam kutip tunggal:
'Coffee'. Angka tidak butuh tanda kutip:WHERE price = 95000. - Perbandingan teks membedakan huruf besar-kecil:
'coffee'tidak cocok dengan apa pun di sini, karena datanya berbunyi'Coffee'.
Kutip ganda punya arti yang berbeda di SQL. "Coffee" dibaca sebagai nama kolom, jadi WHERE category = "Coffee" gagal dengan column "Coffee" does not exist. Kutip tunggal untuk nilai, selalu.
Perhatikan bahwa category tidak ada di daftar SELECT, tapi kamu tetap bisa memfilter dengannya. Database membaca FROM dulu, lalu WHERE, lalu SELECT, jadi setiap kolom tersedia untuk difilter:
| Langkah | Klausa | Apa yang terjadi |
|---|---|---|
| 1 | FROM products | buka tabelnya |
| 2 | WHERE category = 'Coffee' | simpan baris yang cocok |
| 3 | SELECT name, price | simpan kolom-kolom ini |
Operator perbandingan
| Operator | Artinya | Contoh |
|---|---|---|
= | sama dengan | status = 'completed' |
<> atau != | tidak sama dengan | status <> 'cancelled' |
< > | kurang / lebih dari | price > 200000 |
<= >= | paling banyak / minimal | stock <= 20 |
Semuanya bekerja pada angka, teks (urutan alfabetis), dan tanggal. Tanggal ditulis sebagai teks dalam format 'YYYY-MM-DD':
SELECT order_id, order_date, status
FROM orders
WHERE order_date >= '2024-06-20';
order_id | order_date | status
----------+------------+-----------
36 | 2024-06-22 | shipped
37 | 2024-06-24 | cancelled
38 | 2024-06-25 | completed
39 | 2024-06-25 | cancelled
40 | 2024-06-29 | cancelled
(5 rows)
Menggabungkan kondisi: AND, OR, NOT
AND: kedua kondisi harus benar.OR: setidaknya satu harus benar.NOT: membalik sebuah kondisi.
SELECT order_id, order_date, channel
FROM orders
WHERE status = 'completed'
AND channel = 'app'
AND order_date < '2024-03-01';
order_id | order_date | channel
----------+------------+---------
1 | 2024-01-03 | app
3 | 2024-01-17 | app
4 | 2024-01-18 | app
5 | 2024-01-20 | app
9 | 2024-02-14 | app
(5 rows)
Jebakan AND/OR
Ini pertanyaan dari seorang manajer: "Tampilkan produk kopi atau dapur di bawah Rp 100.000." Percobaan pertama yang wajar:
SELECT name, category, price
FROM products
WHERE category = 'Coffee' OR category = 'Kitchen' AND price < 100000;
name | category | price
----------------------+----------+--------
Arabica Gayo 250g | Coffee | 95000
Robusta Lampung 250g | Coffee | 65000
Toraja Kalosi 250g | Coffee | 110000
Ceramic Mug | Kitchen | 55000
(4 rows)
Kopi Toraja harganya Rp 110.000, jadi kenapa ia ada di sana? Karena AND dievaluasi sebelum OR, sama seperti perkalian sebelum penjumlahan di matematika. Database membaca kondisinya sebagai:
category = 'Coffee' OR (category = 'Kitchen' AND price < 100000)
Jadi setiap produk kopi lolos, berapa pun harganya. Tanda kurung memperbaikinya:
SELECT name, category, price
FROM products
WHERE (category = 'Coffee' OR category = 'Kitchen')
AND price < 100000;
name | category | price
----------------------+----------+-------
Arabica Gayo 250g | Coffee | 95000
Robusta Lampung 250g | Coffee | 65000
Ceramic Mug | Kitchen | 55000
(3 rows)
Setiap kali sebuah WHERE mencampur AND dan OR, tambahkan tanda kurung, bahkan saat kamu merasa tidak membutuhkannya. Query-nya tetap jalan tanpa error; hanya angkanya yang salah, dan tidak ada yang menyadarinya sampai terlambat.
IN: OR yang lebih pendek
Saat kamu membandingkan satu kolom dengan beberapa nilai, IN lebih rapi daripada rangkaian OR:
SELECT name, category, price
FROM products
WHERE category IN ('Coffee', 'Kitchen')
AND price < 100000;
name | category | price
----------------------+----------+-------
Arabica Gayo 250g | Coffee | 95000
Robusta Lampung 250g | Coffee | 65000
Ceramic Mug | Kitchen | 55000
(3 rows)
NOT IN menyimpan semuanya kecuali nilai-nilai yang didaftar: WHERE status NOT IN ('cancelled', 'pending').
BETWEEN: sebuah rentang
Pelanggan sering berbelanja sesuai anggaran: "sesuatu antara 60 dan 95 ribu". Kamu bisa menulisnya sebagai price >= 60000 AND price <= 95000, tapi BETWEEN mengatakannya dengan lebih alami. BETWEEN low AND high mencakup kedua ujungnya:
SELECT name, price
FROM products
WHERE price BETWEEN 60000 AND 95000;
name | price
----------------------+-------
Arabica Gayo 250g | 95000
Robusta Lampung 250g | 65000
Desk Organizer | 89000
Scented Candle | 75000
Bamboo Plant | 60000
(5 rows)
Tanaman seharga Rp 60.000 dan kopi seharga Rp 95.000 sama-sama termasuk. Untuk tanggal, order_date BETWEEN '2024-03-01' AND '2024-03-31' berarti "seluruh bulan Maret".
Sedikit tentang nilai yang hilang
Dimas tidak punya email, yang disimpan sebagai NULL. Kamu mungkin mencoba WHERE email = NULL, tapi itu tidak mengembalikan baris sama sekali, karena NULL berarti "tidak diketahui" dan "apakah tidak diketahui sama dengan tidak diketahui?" tidak bernilai benar. Pengujian yang benar adalah IS NULL:
SELECT name, email
FROM customers
WHERE email IS NULL;
name | email
---------------+-------
Dimas Pratama | NULL
Joko Susilo | NULL
(2 rows)
Modul NULL nanti di track ini membahas detailnya. Untuk sekarang: jangan pernah memakai = NULL, pakai IS NULL atau IS NOT NULL.
Mengapa ini penting untuk kode bersih
Sebagian besar angka yang salah di laporan bukan disebabkan oleh crash, melainkan oleh filter yang jalan dengan baik tapi artinya berbeda dari yang dimaksud penulisnya. Tanda kurung di sekitar OR, IN alih-alih rangkaian OR yang panjang, dan satu kondisi per baris membuat maksudmu mustahil salah dibaca, oleh database maupun oleh orang berikutnya.
Rangkuman
WHEREmenyimpan baris-baris yang kondisinya benar; ia berjalan sebelumSELECT.- Teks dan tanggal dalam kutip tunggal; pencocokan teks membedakan huruf besar-kecil.
- Operator:
=,<>,<,>,<=,>=. ANDdievaluasi sebelumOR: selalu pakai tanda kurung saat mencampurnya.IN (...)menggantikan rangkaian OR;BETWEEN a AND bmencakup kedua ujungnya.- Uji nilai yang hilang dengan
IS NULL, jangan pernah= NULL.