TL;DR
Conditional aggregation adalah teknik SQL yang ngitung agregat berbeda per kondisi dalam satu query, pakai pola SUM(CASE WHEN kondisi THEN nilai END). Teknik ini bikin kamu bisa mecah satu kolom kategori jadi banyak kolom metrik, mirip pivot table, tanpa nulis beberapa query terpisah. Pola ini jalan di hampir semua database: PostgreSQL, MySQL, SQL Server, dan BigQuery.
Conditional aggregation adalah teknik SQL buat ngitung agregat yang beda per kondisi dalam satu query. Polanya SUM(CASE WHEN kondisi THEN nilai END).
Teknik ini yang bikin kamu bisa mecah satu kolom kategori jadi banyak kolom metrik. Mirip pivot table, tapi langsung dari query.
Di artikel ini kamu bakal belajar pola dasarnya, beda COUNT dan SUM, cara bikin pivot penjualan UMKM, plus kesalahan yang bikin hasilnya salah diam-diam.
Conditional aggregation ngitung agregat berbeda per kondisi dalam satu query, pakai CASE di dalam fungsi agregat kayak SUM atau COUNT. Tiap kolom hasil bisa punya kondisi sendiri. Jadi kamu bisa naruh penjualan tunai, transfer, dan QRIS jadi tiga kolom berdampingan, semua dari satu tabel.
Bentuk paling dasarnya kayak gini:
SUM(CASE WHEN kondisi THEN nilai END)
Waktu kondisinya cocok, CASE balikin nilainya. Waktu nggak cocok, CASE balikin NULL, dan SUM emang ngabaikan NULL. Itu sebabnya kita sengaja nggak nulis ELSE.
WHERE nyaring baris buat seluruh query, jadi satu query cuma dapet satu kondisi. SUM(CASE WHEN) nyaring di dalam agregat, jadi tiap kolom punya kondisi sendiri. Ini yang bikin kamu bisa ngitung banyak metrik berdampingan dalam satu baris hasil.
Bandingin dua pendekatan ini. Pakai WHERE, kamu butuh dua query:
-- Query 1
SELECT SUM(total) FROM transaksi WHERE metode_bayar = 'tunai';
-- Query 2
SELECT SUM(total) FROM transaksi WHERE metode_bayar = 'transfer';
Pakai conditional aggregation, cukup satu query:
SELECT
SUM(CASE WHEN metode_bayar = 'tunai' THEN total END) AS tunai,
SUM(CASE WHEN metode_bayar = 'transfer' THEN total END) AS transfer
FROM transaksi;
Satu query, dua kolom, hasil langsung sejajar. Ini pola yang sama yang dipakai buat bikin pivot dinamis di SQL.
COUNT ngitung berapa baris yang cocok kondisi, SUM njumlahin nilai dari baris yang cocok. Pakai COUNT buat jumlah transaksi, pakai SUM buat total rupiah. Keduanya sama-sama nggak pakai ELSE biar baris yang nggak cocok jadi NULL dan diabaikan.
-- Hitung jumlah transaksi QRIS
COUNT(CASE WHEN metode_bayar = 'qris' THEN 1 END)
-- Jumlahkan nilai rupiah transaksi QRIS
SUM(CASE WHEN metode_bayar = 'qris' THEN total END)
Buat COUNT, isi THEN-nya bebas asal bukan NULL. Aku biasa pakai angka 1 biar jelas maksudnya cuma ngitung baris.
Kalau kamu masih baru sama logika CASE, cek dulu glosarium CASE WHEN biar paham cara kerjanya baris per baris.
Toko_berkah punya tabel transaksi dengan kolom tanggal, metode_bayar, dan total. Pemilik toko mau laporan bulanan yang nunjukin total tiap metode bayar berdampingan, biar gampang dibaca tanpa scroll.
SELECT
DATE_TRUNC('month', tanggal) AS bulan,
SUM(CASE WHEN metode_bayar = 'tunai' THEN total END) AS tunai,
SUM(CASE WHEN metode_bayar = 'transfer' THEN total END) AS transfer,
SUM(CASE WHEN metode_bayar = 'qris' THEN total END) AS qris
FROM transaksi
GROUP BY DATE_TRUNC('month', tanggal)
ORDER BY bulan;
Hasilnya satu baris per bulan, tiga kolom metode bayar. Dari data 3 bulan terakhir toko_berkah, muncul insight menarik: porsi QRIS naik dari 18% total transaksi di bulan pertama jadi 34% di bulan ketiga. Hampir dua kali lipat dalam tiga bulan.
Angka ini bikin pemilik toko mutusin buat naruh stiker QRIS lebih besar di meja kasir, karena pelanggan jelas makin nyaman bayar non-tunai.
Tanpa conditional aggregation, insight kayak gini butuh tiga query lalu digabung manual di spreadsheet.
Gabungin conditional aggregation dengan GROUP BY pelanggan buat ngitung metrik per segmen. Misal kamu mau tau tiap pelanggan belanja berapa kali di weekday dan berapa kali di weekend, dalam satu baris per pelanggan.
SELECT
pelanggan_id,
COUNT(CASE WHEN EXTRACT(DOW FROM tanggal) IN (0,6) THEN 1 END) AS trx_weekend,
COUNT(CASE WHEN EXTRACT(DOW FROM tanggal) BETWEEN 1 AND 5 THEN 1 END) AS trx_weekday
FROM transaksi
GROUP BY pelanggan_id;
Dari sini kamu bisa lanjut ke segmentasi pelanggan yang lebih dalam, misal misahin pelanggan weekend dan weekday.
Tiga hal ini yang paling sering bikin hasilnya salah tanpa keliatan error.
COUNT(CASE WHEN ... THEN 1 ELSE 0 END), COUNT bakal ngitung 0 juga karena 0 bukan NULL. Hasilnya jadi ngitung semua baris. Buang ELSE-nya, atau ganti COUNT jadi SUM.Teknik ngitung agregat berbeda per kondisi dalam satu query, pakai pola SUM(CASE WHEN kondisi THEN nilai END). Kepakai buat mecah satu kolom kategori jadi banyak kolom metrik berdampingan, mirip pivot table.
Karena kita mau baris yang nggak cocok jadi NULL biar diabaikan agregat. Kalau pakai ELSE 0 di dalam COUNT, semua baris kehitung. Tanpa ELSE, cuma baris yang cocok yang masuk.
Ya. SUM(CASE WHEN) itu standar SQL, jalan di PostgreSQL, MySQL, SQL Server, Oracle, dan BigQuery. Ini pola paling portabel buat conditional aggregation.
PostgreSQL punya klausa FILTER yang lebih ringkas, misal COUNT(*) FILTER (WHERE metode_bayar = 'qris'). Hasilnya sama, cuma sintaksnya lebih bersih.
Conditional aggregation itu satu pola yang kepakai terus-terusan: SUM atau COUNT dibungkus CASE, tanpa ELSE, digabung GROUP BY.
Sekali kamu hafal polanya, laporan yang tadinya butuh tiga query jadi cukup satu.
Mau lanjut belajar pola SQL yang lebih ringkas? Coba klausa FILTER di SQL, dan buat referensi resmi, cek dokumentasi CASE di PostgreSQL.
Mau praktek langsung? Mulai latihan SQL gratis
Latihan interaktif, langsung di browser.
Nambah 30 hari ke tanggal invoice, ngurangin sebulan buat cari periode lalu, ngitung selisih hari antar order. Semua itu aritmetika tanggal, dan SQL punya operator INTERVAL buat ngerjainnya.
Ngurangin tahun sekarang sama tahun lahir kelihatan gampang, tapi hasilnya sering meleset setahun kalau ulang tahunnya belum lewat. Ini cara hitung umur yang akurat di SQL.
Cara pakai DATE_TRUNC di SQL buat memotong timestamp jadi awal bulan, minggu, atau jam. Kunci bikin laporan penjualan per periode yang rapi.