DataLens

Alias dan ekspresi CASE

Beri nama yang jelas, beri label pada baris dengan logika if/then, dan hitung beberapa hal sekaligus dengan agregasi kondisional.

Level: Menengah · 10 menit baca

Latihan modul ini

Soal-soal untuk pelajaran ini berjalan di browser-mu dan langsung mengecek jawabanmu.

Idenya

Dua alat di modul ini membuat query terbaca seperti laporan:

Alias kolom

Kamu sudah memakai AS untuk menamai kolom hasil perhitungan. Beberapa detail lagi:

SELECT name AS product,
       price AS "Unit Price (Rp)",
       price - cost AS margin
FROM products
ORDER BY margin DESC
LIMIT 3;
 product          | Unit Price (Rp) | margin
------------------+-----------------+--------
 USB-C Hub        |          289000 | 119000
 Pour-over Kettle |          320000 | 110000
 Desk Lamp LED    |          245000 | 105000
(3 rows)

Di mana kamu bisa memakai alias? Hanya di klausa yang berjalan setelah SELECT:

KlausaBerjalanBisa memakai alias SELECT?
WHEREsebelum SELECTtidak
HAVINGsebelum SELECTtidak
ORDER BYsetelah SELECTya

(PostgreSQL juga mengizinkan GROUP BY memakai alias sebagai kemudahan, tapi banyak database tidak, jadi track ini mengulang ekspresinya di sana.)

Alias tabel

Kamu juga bisa memberi tabel nama pendek dan memakainya untuk mengatakan dari tabel mana sebuah kolom berasal:

SELECT p.name, p.price
FROM products AS p
WHERE p.category = 'Home';
 name           | price
----------------+--------
 Scented Candle |  75000
 Throw Pillow   | 120000
 Bamboo Plant   |  60000
(3 rows)

Dengan satu tabel sifatnya opsional. Di modul berikutnya, saat query menggabungkan beberapa tabel yang punya nama kolom sama, alias tabel menjadi penting.

CASE: if/then untuk setiap baris

CASE mengecek kondisi-kondisi secara berurutan dan mengembalikan nilai dari kondisi pertama yang benar:

SELECT name,
       price,
       CASE
           WHEN price < 100000 THEN 'budget'
           WHEN price < 200000 THEN 'mid-range'
           ELSE 'premium'
       END AS price_band
FROM products
ORDER BY price;
 name                 | price  | price_band
----------------------+--------+------------
 Gel Pen Set          |  38000 | budget
 Notebook A5 Dotted   |  45000 | budget
 Ceramic Mug          |  55000 | budget
 Bamboo Plant         |  60000 | budget
 Robusta Lampung 250g |  65000 | budget
 Scented Candle       |  75000 | budget
 Desk Organizer       |  89000 | budget
 Arabica Gayo 250g    |  95000 | budget
 Toraja Kalosi 250g   | 110000 | mid-range
 Throw Pillow         | 120000 | mid-range
 Wireless Mouse       | 175000 | mid-range
 French Press 600ml   | 185000 | mid-range
 Desk Lamp LED        | 245000 | premium
 USB-C Hub            | 289000 | premium
 Pour-over Kettle     | 320000 | premium
(15 rows)

Karena kecocokan pertama yang menang, urutan itu penting. Lihat apa yang terjadi kalau kondisi yang lebih luas datang lebih dulu:

SELECT name,
       price,
       CASE
           WHEN price >= 100000 THEN 'mid-range'
           WHEN price >= 200000 THEN 'premium'
           ELSE 'budget'
       END AS price_band
FROM products
WHERE price >= 200000;
 name             | price  | price_band
------------------+--------+------------
 Pour-over Kettle | 320000 | mid-range
 USB-C Hub        | 289000 | mid-range
 Desk Lamp LED    | 245000 | mid-range
(3 rows)

Ketel seharga Rp 320.000 diberi label "mid-range", karena price >= 100000 benar lebih dulu, dan baris premium tidak pernah tercapai. Urutkan kondisi dari yang paling spesifik ke yang paling umum (atau pakai rentang yang tidak bisa tumpang tindih).

Mengelompokkan berdasarkan CASE

CASE membuat kolom baru, dan kamu bisa mengelompokkan berdasarkan kolom itu seperti kolom lainnya:

SELECT CASE
           WHEN price < 100000 THEN 'budget'
           WHEN price < 200000 THEN 'mid-range'
           ELSE 'premium'
       END AS price_band,
       COUNT(*) AS products
FROM products
GROUP BY 1
ORDER BY products DESC;
 price_band | products
------------+----------
 budget     |        8
 mid-range  |        4
 premium    |        3
(3 rows)

GROUP BY 1 berarti "kelompokkan berdasarkan kolom pertama di SELECT". Ini menghemat pengulangan CASE yang panjang, dan umum di pekerjaan analitik.

Agregasi kondisional

Ini salah satu pola paling berguna di SQL analitik. Hitung beberapa hal dalam satu kali jalan dengan menaruh CASE di dalam agregat:

SELECT channel,
       COUNT(*) AS orders,
       SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) AS completed,
       SUM(CASE WHEN status = 'cancelled' THEN 1 ELSE 0 END) AS cancelled
FROM orders
GROUP BY channel
ORDER BY channel;
 channel | orders | completed | cancelled
---------+--------+-----------+-----------
 app     |     12 |        10 |         2
 web     |     28 |        16 |         8
(2 rows)

Setiap baris menambahkan 1 ke completed kalau ia completed, 0 kalau tidak, jadi SUM-nya menghitung pesanan completed. Kamu sudah mengubah nilai-nilai status menjadi kolom, persis seperti pivot table.

PostgreSQL punya ejaan yang lebih rapi untuk hal yang sama, FILTER:

SELECT channel,
       COUNT(*) FILTER (WHERE status = 'completed') AS completed,
       ROUND(100.0 * COUNT(*) FILTER (WHERE status = 'cancelled') / COUNT(*), 1) AS cancel_rate
FROM orders
GROUP BY channel
ORDER BY channel;
 channel | completed | cancel_rate
---------+-----------+-------------
 app     |        10 |        16.7
 web     |        16 |        28.6
(2 rows)

Versi SUM(CASE ...) bekerja di setiap database. FILTER lebih pendek dan lebih enak dibaca, tapi khusus PostgreSQL (dan beberapa database lain).

Mengapa ini penting untuk kode bersih

CASE menaruh aturan bisnis di satu tempat yang terlihat. "Premium berarti Rp 200.000 ke atas" tinggal di query, bukan di ingatan seseorang atau formula Excel yang tersembunyi. Saat aturannya berubah, kamu mengubah satu baris. Pasangkan dengan alias yang jelas dan query-mu menjadi dokumentasi tentang cara sebuah angka dihitung.

Rangkuman

Latihan modul ini

Soal-soal untuk pelajaran ini berjalan di browser-mu dan langsung mengecek jawabanmu.