TL;DR
Klausa FILTER di SQL bikin fungsi agregat cuma ngitung baris yang cocok kondisi tertentu, pakai bentuk COUNT(*) FILTER (WHERE kondisi). Ini alternatif yang lebih ringkas dan lebih gampang dibaca dibanding pola SUM(CASE WHEN). FILTER didukung PostgreSQL dan SQLite modern, tapi belum ada di MySQL, jadi buat MySQL kamu tetap pakai CASE WHEN.
Klausa FILTER di SQL bikin fungsi agregat cuma ngitung baris yang cocok kondisi tertentu. Bentuknya COUNT(*) FILTER (WHERE kondisi).
Ini alternatif yang lebih bersih buat pola SUM(CASE WHEN) yang sering panjang dan susah dibaca.
Di artikel ini kamu bakal belajar sintaks FILTER, bandinginnya sama CASE WHEN, contoh nyata dari data order UMKM, plus kapan sebaiknya nggak pakai FILTER.
FILTER nempel di fungsi agregat biar cuma ngitung baris yang cocok kondisi. Bentuknya fungsi agregat diikuti FILTER (WHERE kondisi). Ini bikin kamu bisa naruh beberapa metrik bersyarat berdampingan dalam satu query, dengan sintaks yang lebih ringkas dari CASE WHEN.
COUNT(*) FILTER (WHERE status = 'lunas')
Baris yang statusnya bukan lunas nggak ikut kehitung. Nggak perlu CASE, nggak perlu THEN, tinggal tulis kondisinya langsung.
FILTER ini pada dasarnya cara lain buat conditional aggregation, dengan hasil yang persis sama.
Keduanya bikin agregasi bersyarat dan hasilnya identik. Bedanya di sintaks dan dukungan database. FILTER lebih pendek dan lebih jelas maksudnya, tapi cuma jalan di PostgreSQL dan SQLite modern. CASE WHEN lebih panjang tapi jalan di mana pun.
Bandingin dua versi ini yang ngitung hal yang sama:
-- Versi CASE WHEN
COUNT(CASE WHEN status = 'lunas' THEN 1 END) AS lunas
-- Versi FILTER
COUNT(*) FILTER (WHERE status = 'lunas') AS lunas
Versi FILTER lebih gampang dibaca, apalagi kalau kondisinya rumit. Waktu satu query punya lima metrik bersyarat, selisih keterbacaannya kerasa banget.
Bisa. FILTER jalan sama semua fungsi agregat: COUNT, SUM, AVG, MIN, dan MAX. Kamu tinggal tempel FILTER (WHERE kondisi) setelah fungsinya. Ini berguna buat ngitung total atau rata-rata dari subset data tanpa subquery terpisah.
SUM(total) FILTER (WHERE status = 'lunas') AS omzet_lunas,
AVG(total) FILTER (WHERE metode_bayar = 'qris') AS rata_qris
Baris pertama njumlahin total cuma dari order lunas. Baris kedua ngitung rata-rata nilai order cuma buat yang bayar QRIS. Semua dalam satu query.
Toko_berkah punya tabel transaksi dengan kolom tanggal, status, metode_bayar, dan total. Pemilik toko mau satu laporan bulanan yang nunjukin total order, order lunas, order batal, dan omzet lunas, semua berdampingan.
SELECT
DATE_TRUNC('month', tanggal) AS bulan,
COUNT(*) AS total_order,
COUNT(*) FILTER (WHERE status = 'lunas') AS lunas,
COUNT(*) FILTER (WHERE status = 'batal') AS batal,
SUM(total) FILTER (WHERE status = 'lunas') AS omzet
FROM transaksi
GROUP BY DATE_TRUNC('month', tanggal)
ORDER BY bulan;
Dari data tiga bulan, muncul insight yang bikin pemilik toko kaget: tingkat pembatalan order naik dari 6% di bulan pertama jadi 14% di bulan ketiga. Lebih dari dua kali lipat.
Setelah ditelusuri, ternyata order batal paling banyak dari metode bayar transfer yang pelanggannya sering lupa bayar. Pemilik toko lalu mindahin default pembayaran ke QRIS, dan angka batal turun lagi bulan berikutnya.
Query yang sama pakai CASE WHEN bakal dua kali lebih panjang dan lebih capek dibaca.
Pakai CASE WHEN kalau database kamu nggak dukung FILTER, terutama MySQL. Pakai juga CASE WHEN kalau query kamu harus jalan di beberapa jenis database sekaligus. Buat itu, CASE WHEN lebih aman karena portabel.
| Kondisi | Pilihan |
|---|---|
| Pakai PostgreSQL atau SQLite | FILTER |
| Pakai MySQL | CASE WHEN |
| Query harus portabel | CASE WHEN |
| Mau kode paling bersih | FILTER |
Buat ngerti dasar logikanya, cek glosarium CASE WHEN.
FILTER nempel di fungsi agregat biar cuma ngitung baris yang cocok kondisi, bentuknya COUNT(*) FILTER (WHERE kondisi). Alternatif yang lebih ringkas dari SUM(CASE WHEN) buat agregasi bersyarat.
Hasilnya sama, sintaksnya beda. FILTER lebih pendek tapi cuma jalan di PostgreSQL dan SQLite. CASE WHEN lebih panjang tapi jalan di semua database.
Belum. Buat MySQL, pakai pola SUM(CASE WHEN) atau COUNT(CASE WHEN). FILTER didukung PostgreSQL sejak 9.4 dan SQLite sejak 3.30.
Bisa. FILTER jalan sama COUNT, SUM, AVG, MIN, dan MAX. Contohnya SUM(total) FILTER (WHERE status = 'lunas').
FILTER bikin agregasi bersyarat jauh lebih enak dibaca daripada CASE WHEN. Inti pakainya: fungsi agregat, lalu FILTER (WHERE kondisi).
Ingat satu batasan: FILTER belum ada di MySQL, jadi cek dulu database kamu.
Mau lanjut ke pola agregasi lain? Cek pivot dinamis di SQL dan referensi resmi di dokumentasi agregat 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.