SQL bukan bahasa pemrograman imperatif — tidak ada if atau else berdiri sendiri. Tetapi kebutuhan “jika harganya di atas 50000 maka labelnya Mahal” tetap harus dijawab di dalam query, bukan di kode aplikasi. Ekspresi CASE adalah alat kondisionalnya SQL: sebuah ekspresi (bukan statement) yang menilai serangkaian syarat lalu menghasilkan satu nilai. Karena berstatus ekspresi, CASE bisa hadir di mana pun nilai boleh berada — kolom SELECT, klausa ORDER BY, hingga di dalam fungsi agregat — dan tiga penempatan itulah yang kita praktikkan di chapter penutup section ini.
Data Contoh #
Empat tabel domain toko dipakai pada chapter ini (query utamanya menyentuh produk, pelanggan, dan detail_pesanan):
CREATE TABLE pelanggan (
id INTEGER PRIMARY KEY,
nama TEXT NOT NULL,
kota TEXT
);
CREATE TABLE produk (
id INTEGER PRIMARY KEY,
nama TEXT NOT NULL,
harga INTEGER NOT NULL,
stok INTEGER
);
CREATE TABLE pesanan (
id INTEGER PRIMARY KEY,
pelanggan_id INTEGER REFERENCES pelanggan(id),
tanggal TEXT NOT NULL
);
CREATE TABLE detail_pesanan (
pesanan_id INTEGER REFERENCES pesanan(id),
produk_id INTEGER REFERENCES produk(id),
jumlah INTEGER NOT NULL,
PRIMARY KEY (pesanan_id, produk_id)
);
INSERT INTO pelanggan (id, nama, kota) VALUES
(1, 'Budi', 'Jakarta'), (2, 'Siti', 'Bandung'), (3, 'Ani', NULL),
(4, 'Rina', 'Surabaya'), (5, 'Dewi', 'Jakarta');
INSERT INTO produk (id, nama, harga, stok) VALUES
(1, 'Kopi Gayo', 45000, 20), (2, 'Teh Melati', 18000, 35),
(3, 'Gula Aren', 25000, 15), (4, 'Sirup Vanila', 25000, NULL),
(5, 'Kopi Toraja', 52000, 10), (6, 'Teh Hijau', 22000, 0),
(7, 'Cangkir Keramik', 35000, 8);
INSERT INTO pesanan (id, pelanggan_id, tanggal) VALUES
(1, 1, '2025-06-01'), (2, 2, '2025-06-03'), (3, 1, '2025-06-07'),
(4, 3, '2025-06-10'), (5, 2, '2025-06-15'), (6, 1, '2025-07-02');
INSERT INTO detail_pesanan (pesanan_id, produk_id, jumlah) VALUES
(1, 1, 2), (1, 3, 1), (2, 2, 3), (3, 1, 1),
(3, 4, 2), (4, 5, 1), (5, 6, 2), (5, 3, 2), (6, 1, 1);Simple CASE dan Searched CASE #
SQLite mengenal dua bentuk. Simple CASE membandingkan satu ekspresi terhadap sekumpulan nilai:
SELECT pesanan_id, produk_id,
CASE jumlah
WHEN 1 THEN 'satu unit'
WHEN 2 THEN 'dua unit'
WHEN 3 THEN 'tiga unit'
END AS label
FROM detail_pesanan
ORDER BY pesanan_id, produk_id;Output yang Dihasilkan:
1|1|dua unit
1|3|satu unit
2|2|tiga unit
3|1|satu unit
3|4|dua unit
4|5|satu unit
5|3|dua unit
5|6|dua unit
6|1|satu unitNilai jumlah dibandingkan dengan tiap WHEN berurutan; WHEN pertama yang cocok menang, dan sisanya diabaikan. Tanpa ELSE, nilai yang tidak kena satu pun WHEN menghasilkan NULL — pada data kita semua jumlah sudah terwakili 1, 2, dan 3. Perlu dicatat juga bahwa simple CASE memakai kesamaan nilai persis seperti operator =; begitu syaratnya berupa rentang atau kombinasi logika, searched CASE adalah bentuk yang tepat.
Searched CASE menilai syarat bebas pada tiap WHEN — bentuk yang jauh lebih umum karena mendukung rentang dan kombinasi:
SELECT nama, harga,
CASE
WHEN harga >= 50000 THEN 'Mahal'
WHEN harga >= 30000 THEN 'Sedang'
ELSE 'Murah'
END AS kategori
FROM produk
ORDER BY harga DESC;Output yang Dihasilkan:
Kopi Toraja|52000|Mahal
Kopi Gayo|45000|Sedang
Cangkir Keramik|35000|Sedang
Gula Aren|25000|Murah
Sirup Vanila|25000|Murah
Teh Hijau|22000|Murah
Teh Melati|18000|MurahUrutan WHEN menentukan hasil: Kopi Gayo (45000) gagal di syarat pertama, lulus di syarat kedua. Jika kedua syarat itu ditukar, semua produk di bawah 50000 akan berlabel Murah.
CASE dan NULL: Uji Eksplisit #
Syarat pada WHEN hanya menerima hasil benar; NULL tidak pernah dianggap cocok, jadi pengujian NULL harus eksplisit. Contoh berikut memberi label stok dengan WHEN stok IS NULL di urutan pertama:
SELECT nama, stok,
CASE
WHEN stok IS NULL THEN 'Tidak diketahui'
WHEN stok = 0 THEN 'Habis'
WHEN stok < 15 THEN 'Menipis'
ELSE 'Aman'
END AS status
FROM produk
ORDER BY id;Output yang Dihasilkan:
Kopi Gayo|20|Aman
Teh Melati|35|Aman
Gula Aren|15|Aman
Sirup Vanila||Tidak diketahui
Kopi Toraja|10|Menipis
Teh Hijau|0|Habis
Cangkir Keramik|8|MenipisSirup Vanila berlabel Tidak diketahui karena syarat WHEN stok IS NULL berada di urutan pertama — tanpa syarat itu, Sirup Vanila akan jatuh ke ELSE dengan label yang menyesatkan.
CASE di ORDER BY: Urutan Khusus #
Karena CASE adalah ekspresi, ia bisa menjadi kunci ORDER BY — satu-satunya cara membuat urutan khusus yang tidak mengikuti urutan alfabetis atau angka. Query berikut mendahulukan pelanggan Jakarta, lalu Bandung, sisanya belakang:
SELECT nama, kota
FROM pelanggan
ORDER BY CASE kota WHEN 'Jakarta' THEN 1 WHEN 'Bandung' THEN 2 ELSE 3 END,
nama;Output yang Dihasilkan:
Budi|Jakarta
Dewi|Jakarta
Siti|Bandung
Ani|
Rina|SurabayaCASE mengubah tiap kota menjadi angka 1-3, dan nama menjadi pemecah seri. Pelanggan berkota NULL mendapat ELSE — nilai 3 — karena NULL = 'Jakarta' bernilai NULL, bukan benar.
Pivot: Agregat plus CASE #
Kombinasi agregat dan CASE menghasilkan pola pivot — menjawab beberapa pertanyaan sekaligus dalam satu baris. Triknya: CASE menghasilkan 1 atau 0, lalu SUM menghitungnya per kolom:
SELECT
SUM(CASE WHEN harga >= 30000 THEN 1 ELSE 0 END) AS mahal_sedang,
SUM(CASE WHEN harga < 30000 THEN 1 ELSE 0 END) AS murah
FROM produk;Output yang Dihasilkan:
3|4Tiga produk berharga 30000 ke atas dan empat di bawahnya, dalam satu baris ringkasan. SQLite juga menyediakan klausa FILTER — sejak versi 3.30 — yang menulis pola yang sama lebih ringkas: agregat hanya menghitung baris yang lolos syaratnya:
SELECT
COUNT(*) FILTER (WHERE harga >= 30000) AS mahal_sedang,
COUNT(*) FILTER (WHERE harga < 30000) AS murah
FROM produk;Output yang Dihasilkan:
3|4Dengan CASE, kotak perkakas query kita lengkap: operator penyaring, agregasi, penggabungan tabel, subquery, CTE, window functions, operasi set, dan kini logika kondisional. Section berikutnya meninggalkan query tunggal dan membahas apa yang terjadi ketika banyak query berjalan bersamaan: transaksi dan konsistensi.