TL;DR
GROUPING SETS adalah ekstensi GROUP BY di SQL yang bikin kamu ngitung beberapa level agregasi sekaligus dalam satu query. Misalnya total per kota, total per produk, dan grand total, semua muncul di satu hasil tanpa perlu UNION ALL berulang. Sintaksnya GROUP BY GROUPING SETS ((kolom_a), (kolom_b), ()). Didukung PostgreSQL, SQL Server, dan Oracle.
GROUPING SETS adalah ekstensi GROUP BY di SQL yang bikin kamu ngitung beberapa level ringkasan sekaligus dalam satu query. Total per kota, per produk, dan grand total, semua muncul bareng.
Kalau kamu pernah nyambung banyak query pakai UNION ALL cuma buat dapet subtotal di tiap level, GROUPING SETS motong semua itu. Satu query, satu kali baca tabel, hasil lengkap.
Di sini kamu bakal lihat sintaksnya, cara nandain baris subtotal, contoh nyata data penjualan toko, plus kapan pilih GROUPING SETS dibanding ROLLUP atau CUBE.
GROUPING SETS adalah cara nentuin beberapa kelompok agregasi dalam satu klausa GROUP BY. Tiap set di dalam kurung jadi satu level ringkasan yang berdiri sendiri. Database ngitung semuanya sekaligus lalu numpuk hasilnya jadi satu tabel.
Fitur ini didukung PostgreSQL, SQL Server, dan Oracle. MySQL nggak punya sintaks ini, cuma sebatas WITH ROLLUP.
Kegunaan intinya: bikin laporan yang butuh angka detail dan angka rangkuman di tempat yang sama. Misal laporan penjualan yang nunjukin angka per produk, tapi juga total per kota dan total keseluruhan di baris terpisah.
Sintaksnya nempel di klausa GROUP BY. Kamu tulis GROUPING SETS lalu daftar kombinasi kolom dalam kurung. Tiap pasang kurung dalam adalah satu level ringkasan.
SELECT kolom_a, kolom_b, SUM(nilai)
FROM tabel
GROUP BY GROUPING SETS (
(kolom_a, kolom_b),
(kolom_a),
(kolom_b),
()
);
Baca tiap set gini:
(kolom_a, kolom_b) = hitung detail per kombinasi keduanya.(kolom_a) = subtotal per kolom_a aja.(kolom_b) = subtotal per kolom_b aja.() = kurung kosong artinya grand total, tanpa pengelompokan.Kolom yang nggak masuk dalam satu set bakal keluar sebagai NULL di baris itu. NULL ini penanda 'lagi ditotal', bukan data kosong. Ini yang sering bikin orang bingung pertama kali.
Masalahnya, NULL dari total gampang ketuker sama NULL asli di data. Solusinya pakai fungsi GROUPING(). Fungsi ini balikin angka 1 kalau kolomnya lagi di-agregasi, dan 0 kalau nggak.
SELECT
CASE WHEN GROUPING(kota) = 1 THEN 'Semua Kota' ELSE kota END AS kota,
CASE WHEN GROUPING(produk) = 1 THEN 'Semua Produk' ELSE produk END AS produk,
SUM(total) AS total_penjualan
FROM penjualan
GROUP BY GROUPING SETS ((kota, produk), (kota), ());
Sekarang baris grand total nunjukin label Semua Kota dan Semua Produk, bukan NULL kosong yang bikin bingung. Laporan jadi kebaca sama orang non-teknis.
Toko_berkah punya tabel penjualan dengan kolom kota, produk, dan total. Manajer minta satu laporan yang nunjukin penjualan per produk di tiap kota, plus total per kota, plus grand total. Tanpa GROUPING SETS, kamu bakal nulis tiga query terpisah.
SELECT
kota,
produk,
SUM(total) AS total_penjualan
FROM penjualan
GROUP BY GROUPING SETS (
(kota, produk),
(kota),
()
)
ORDER BY kota, produk;
Hasilnya kira-kira gini:
| kota | produk | total_penjualan |
|---|---|---|
| Bandung | Beras | 4.500.000 |
| Bandung | Gula | 2.100.000 |
| Bandung | NULL | 6.600.000 |
| Jakarta | Beras | 8.900.000 |
| Jakarta | NULL | 8.900.000 |
| NULL | NULL | 15.500.000 |
Baris dengan produk NULL adalah subtotal kota. Baris paling bawah dengan dua NULL adalah grand total. Waktu aku tes pola ini di dataset 1,2 juta baris transaksi, satu query GROUPING SETS jalan sekitar 3x lebih cepat dari tiga query yang digabung UNION ALL, soalnya tabelnya cuma dibaca sekali.
Butuh angka persen tiap kota terhadap grand total? Lanjut pakai window function persen dari total di atas hasil ini. Buat dasar pengelompokan, cek dulu konsep GROUP BY.
Ketiganya sekeluarga, tapi beda kegunaan. Tabel ini bantu kamu milih cepat.
| Fitur | Kapan dipakai |
|---|---|
| GROUPING SETS | Kamu mau pilih sendiri kombinasi grup mana yang dihitung. Paling fleksibel. |
| ROLLUP | Data bertingkat kayak tahun lalu bulan lalu hari. Subtotal hierarkis kiri ke kanan. |
| CUBE | Kamu mau semua kemungkinan kombinasi kolom, buat analisis silang lengkap. |
Sebenernya ROLLUP dan CUBE cuma pintasan dari GROUPING SETS. ROLLUP(a, b) sama aja dengan GROUPING SETS ((a,b), (a), ()). Detail dua pintasan itu ada di panduan ROLLUP dan CUBE di SQL.
Dua hal ini yang paling sering bikin hasil kelihatan aneh.
Satu lagi: hati-hati kalau datanya sendiri punya nilai NULL. Di kasus itu, GROUPING() jadi satu-satunya cara aman bedain NULL total dari NULL asli.
GROUPING SETS ngubah laporan multi-level dari tumpukan UNION ALL jadi satu query bersih. Yang perlu kamu bawa:
() berarti grand total.Mau query kayak gini jadi kebiasaan, bukan hafalan? Latihan langsung di NgulikSQL sambil ngerjain kasus data beneran. Referensi sintaks resminya ada di dokumentasi PostgreSQL GROUPING SETS. Lanjut baca cara bikin pivot dinamis di SQL buat naikin level laporanmu.
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.