Data nyata hampir tidak pernah tiba dalam kondisi bersih. Kolom kota bisa kosong, kategori perlu diterjemahkan menjadi label segmen, dan status pesanan yang tersusun dalam baris perlu diputar menjadi kolom agar mudah dibaca. SQL menyediakan tiga perangkat untuk situasi ini: CASE WHEN untuk logika kondisional, COALESCE untuk menggantikan NULL, dan NULLIF untuk mencegah nilai bermasalah ikut dihitung — bahan dasar hampir setiap query transformasi pada pipeline. Seluruh contoh dijalankan nyata di SQLite pada database toko online dari Chapter Common Table Expressions.
CASE WHEN: Logika If-Else di SQL #
CASE WHEN mengevaluasi kondisi secara berurutan dari atas dan mengembalikan nilai dari cabang pertama yang terpenuhi. Contoh berikut melabeli setiap produk menjadi segmen harga:
SELECT nama, harga,
CASE
WHEN harga >= 1000000 THEN 'Premium'
WHEN harga >= 200000 THEN 'Menengah'
ELSE 'Ekonomis'
END AS segmen
FROM produk
ORDER BY harga DESC;Output yang Dihasilkan:
nama | harga | segmen
Laptop Pro 14 | 12500000 | Premium
Smartphone X1 | 3500000 | Premium
Sneakers Klasik | 900000 | Menengah
TWS Earbuds | 750000 | Menengah
Dress Summer | 380000 | Menengah
Kemeja Batik | 250000 | Menengah
Kemeja Flanel | 180000 | Ekonomis
Buku Sains Data | 145000 | Ekonomis
Novel Laut Bercerita | 110000 | Ekonomis
Kaos Polos Katun | 95000 | EkonomisMari kita telaah cara kerja ekspresi di atas:
WHEN harga >= 1000000 THEN 'Premium': kondisi pertama diperiksa lebih dulu; produk berharga satu juta ke atas berhenti di sini.WHEN harga >= 200000 THEN 'Menengah': hanya diuji bila kondisi pertama gagal — urutan cabang menentukan arti label.ELSE 'Ekonomis': penampung kondisi yang gagal — tanpaELSE, nilai yang tidak lolos menjadiNULL.END AS segmen: penutup wajibCASE, diikuti alias kolom hasilnya.
Label segmen biasanya tidak disimpan di tabel sumber — label didefinisikan di query agar aturan bisnis bisa berubah tanpa memigrasi data, dan pola yang sama bekerja di dalam ORDER BY maupun WHERE.
Agregasi Kondisional: SUM(CASE WHEN …) #
Kekuatan CASE baru terasa di dalam fungsi agregasi. Trik SUM(CASE WHEN kondisi THEN 1 ELSE 0 END) menghitung baris yang memenuhi kondisi, dan pola ini mengubah data baris-per-status menjadi tabel pivot yang mudah dibaca:
SELECT COALESCE(p.kota, 'Tidak diketahui') AS kota,
COUNT(*) AS total_pesanan,
SUM(CASE WHEN ps.status = 'selesai' THEN 1 ELSE 0 END) AS selesai,
SUM(CASE WHEN ps.status = 'dikirim' THEN 1 ELSE 0 END) AS dikirim,
SUM(CASE WHEN ps.status = 'diproses' THEN 1 ELSE 0 END) AS diproses,
SUM(CASE WHEN ps.status = 'menunggu' THEN 1 ELSE 0 END) AS menunggu,
SUM(CASE WHEN ps.status = 'dibatalkan' THEN 1 ELSE 0 END) AS dibatalkan
FROM pelanggan p
JOIN pesanan ps ON ps.pelanggan_id = p.id
GROUP BY p.kota
ORDER BY kota;Output yang Dihasilkan:
kota | total_pesanan | selesai | dikirim | diproses | menunggu | dibatalkan
Bandung | 2 | 1 | 0 | 1 | 0 | 0
Jakarta | 4 | 2 | 1 | 0 | 0 | 1
Surabaya | 2 | 1 | 0 | 1 | 0 | 0
Tidak diketahui | 1 | 1 | 0 | 0 | 0 | 0Tiap kolom SUM(CASE ...) menghitung satu nilai status — Jakarta memiliki dua pesanan selesai karena hanya baris berstatus cocok yang menyumbang angka 1 — dan GROUP BY p.kota menggabungkan pesanan Budi dan Rina, dua pelanggan Jakarta, menjadi satu baris berisi empat pesanan. Kolom menunggu tetap nol di semua kota karena tidak ada pesanan berstatus tersebut — daftar kolom pada query yang menentukan bentuk pivot, bukan nilai yang kebetulan ada.
COALESCE(p.kota, 'Tidak diketahui') membuat pesanan Andi yang kotanya NULL tetap terhitung dengan label pengganti. PostgreSQL dan SQLite modern juga menyediakan klausul FILTER (WHERE ...) yang lebih ringkas, tetapi SUM(CASE ...) tetap paling portabel antar database.
COALESCE dan NULLIF: Menjinakkan NULL #
NULL bukan string kosong dan bukan nol — NULL menandakan nilai yang tidak ada. Pembandingan NULL = NULL pun tidak menghasilkan benar, sehingga WHERE kota = NULL tidak pernah cocok. Dua fungsi menangani dua arah masalah ini:
COALESCE(nilai1, nilai2, ...)mengembalikan nilai pertama yang tidakNULL— seperti label kota pada pivot di atas.NULLIF(a, b)mengembalikanNULLbilaa = b, danabila berbeda — dipakai menetralkan nilai bermasalah sebelum dihitung.
Kasus nyatanya: detail pesanan 5 — pesanan yang dibatalkan — menyimpan subtotal NULL, dan data kotor dari sistem lain bisa mengirim jumlah = 0. NULLIF membuat pembagian oleh nol mustahil terjadi pada perhitungan harga satuan:
SELECT d.pesanan_id, pr.nama, d.jumlah, d.subtotal,
d.subtotal / NULLIF(d.jumlah, 0) AS harga_satuan
FROM detail_pesanan d
JOIN produk pr ON pr.id = d.produk_id
WHERE d.pesanan_id IN (4, 5)
ORDER BY d.pesanan_id, d.produk_id;Output yang Dihasilkan:
pesanan_id | nama | jumlah | subtotal | harga_satuan
4 | Kemeja Batik | 1 | 250000 | 250000
4 | Sneakers Klasik | 1 | 900000 | 900000
5 | Dress Summer | 1 | NULL | NULLNULLIF(d.jumlah, 0) mengubah 0 menjadi NULL sebelum menjadi pembagi, sehingga bila data kotor mengirim jumlah = 0, baris tersebut menghasilkan NULL alih-alih angka keliru; baris valid tetap normal — 250000 / 1 = 250000. Sementara itu subtotal NULL pada pesanan 5 menular ke harga_satuan karena NULL dalam aritmetika apa pun tetap NULL.
Catatan Dialek: NVL dan ILIKE #
Sebagian besar ekspresi kondisional berupa SQL standar, tetapi tiap database menyimpan kebiasaan dialeknya sendiri:
| Ekspresi | Database | Keterangan |
|---|---|---|
COALESCE(a, b) | standar SQL, semua database | mengembalikan nilai pertama yang tidak NULL |
IFNULL(a, b) | SQLite, MySQL | padanan COALESCE dua argumen |
NVL(a, b) | Oracle | padanan COALESCE dua argumen pada database Oracle |
ILIKE 'pola' | PostgreSQL | pencarian LIKE tanpa membedakan huruf besar-kecil |
Contoh kolom terakhir: mencari produk yang memuat kata buku memerlukan ILIKE '%buku%' di PostgreSQL, sementara LIKE SQLite sudah bersifat demikian untuk huruf ASCII. Untuk query lintas database, utamakan bentuk standar seperti COALESCE dan LOWER(nama) LIKE ...; rujukan resminya di dokumentasi SQLite
dan PostgreSQL
.
Dengan CASE WHEN, agregasi kondisional, dan penanganan NULL, perangkat membentuk data laporan kita lengkap — dan seluruhnya berjalan dalam mode baca. Padahal pipeline juga harus menulis: memuat baris baru, memperbaiki nilai, membersihkan sisa data. Chapter berikutnya, Manipulasi Data, membahas INSERT, UPDATE, DELETE, dan pola UPSERT untuk penulisan data yang aman.