TL;DR
ROLLUP bikin subtotal hierarkis dari kiri ke kanan plus grand total, cocok buat data bertingkat kayak tahun lalu bulan. CUBE bikin subtotal untuk semua kemungkinan kombinasi kolom sekaligus. Sintaksnya GROUP BY ROLLUP(kolom1, kolom2) atau GROUP BY CUBE(kolom1, kolom2). Keduanya pintasan dari GROUPING SETS dan didukung PostgreSQL, SQL Server, serta Oracle.
ROLLUP bikin subtotal bertingkat plus grand total otomatis, CUBE bikin subtotal untuk semua kombinasi kolom sekaligus. Dua pintasan SQL buat laporan yang butuh angka rangkuman di banyak level.
Kalau kamu sering diminta laporan yang nunjukin total per bulan, subtotal per tahun, dan grand total dalam satu tabel, ROLLUP ngerjain itu semua dalam satu klausa. Nggak perlu query terpisah tiap level.
Di sini kamu bakal lihat sintaks keduanya, beda cara kerjanya, cara nandain baris subtotal, plus contoh laporan penjualan toko.
ROLLUP dan CUBE adalah ekstensi GROUP BY buat ngitung subtotal dan grand total dalam satu query. ROLLUP ngasih subtotal hierarkis dari kiri ke kanan. CUBE ngasih subtotal untuk tiap kemungkinan kombinasi kolom.
Keduanya sebenernya pintasan dari GROUPING SETS. Bedanya, ROLLUP dan CUBE nulis pola umum secara ringkas, sementara GROUPING SETS bikin kamu nentuin tiap grup manual.
Fitur ini didukung PostgreSQL, SQL Server, dan Oracle. MySQL cuma punya WITH ROLLUP, nggak ada CUBE.
ROLLUP numpuk subtotal dari kolom paling kanan ke kiri. Buat ROLLUP(tahun, bulan), kamu dapat tiga level: detail per tahun-bulan, subtotal per tahun, dan grand total.
SELECT
tahun,
bulan,
SUM(total) AS total_penjualan
FROM penjualan
GROUP BY ROLLUP (tahun, bulan)
ORDER BY tahun, bulan;
Hasilnya kira-kira gini:
| tahun | bulan | total_penjualan |
|---|---|---|
| 2026 | 1 | 12.000.000 |
| 2026 | 2 | 15.000.000 |
| 2026 | NULL | 27.000.000 |
| NULL | NULL | 27.000.000 |
Baris dengan bulan NULL adalah subtotal tahun. Baris dua NULL adalah grand total. Perhatiin ROLLUP nggak ngasih subtotal per bulan lintas tahun. Itu bagian yang cuma bisa dari CUBE.
CUBE bikin subtotal untuk semua kombinasi kolom. Buat CUBE(kota, produk), kamu dapat empat level: per kota-produk, per kota, per produk, dan grand total.
SELECT
kota,
produk,
SUM(total) AS total_penjualan
FROM penjualan
GROUP BY CUBE (kota, produk)
ORDER BY kota, produk;
Bedanya sama ROLLUP: CUBE ngasih subtotal per produk yang berdiri sendiri lintas kota. ROLLUP nggak. Aturan jumlahnya: CUBE menghasilkan 2 pangkat n level, di mana n jumlah kolom. Dua kolom berarti 4 level. Tiga kolom langsung 8 level. Makin banyak kolom, makin banyak baris subtotal.
NULL dari subtotal gampang ketuker sama NULL asli di data. Pakai fungsi GROUPING() buat bedain. Fungsi ini balikin 1 kalau kolomnya lagi di-agregasi, 0 kalau nggak.
SELECT
CASE WHEN GROUPING(tahun) = 1 THEN 'Semua Tahun' ELSE tahun::text END AS tahun,
CASE WHEN GROUPING(bulan) = 1 THEN 'Total' ELSE bulan::text END AS bulan,
SUM(total) AS total_penjualan
FROM penjualan
GROUP BY ROLLUP (tahun, bulan);
Sekarang baris subtotal nunjukin label Total, bukan NULL kosong. Laporan langsung kebaca tanpa perlu dijelasin.
Toko_berkah mau laporan penjualan yang nunjukin total per bulan, subtotal per tahun, dan grand total, dalam satu tabel. Ini kasus klasik buat ROLLUP karena datanya bertingkat: tahun di atas, bulan di bawah.
SELECT
tahun,
bulan,
SUM(total) AS total_penjualan
FROM penjualan
GROUP BY ROLLUP (tahun, bulan)
ORDER BY tahun, bulan;
Waktu aku pakai ROLLUP di data 24 bulan dengan 890 ribu transaksi, satu query ini ngasih 24 baris detail plus 2 baris subtotal tahun plus 1 grand total, semua dalam sekali jalan. Sebelumnya butuh tiga query terpisah yang digabung, dan tabelnya kebaca tiga kali. ROLLUP baca sekali.
Butuh persen tiap bulan terhadap total tahun? Lanjut pakai window function persen dari total. Buat pengelompokan dasar, pahami dulu konsep GROUP BY. Kalau kamu butuh kombinasi grup yang lebih spesifik, GROUPING SETS lebih pas.
Tabel ini bantu kamu milih cepat.
| Fitur | Yang dihasilkan | Kapan dipakai |
|---|---|---|
| ROLLUP | Subtotal hierarkis kiri ke kanan + grand total | Data bertingkat: tahun, bulan, hari |
| CUBE | Semua kombinasi subtotal | Analisis silang penuh antar dimensi |
| GROUPING SETS | Cuma kombinasi yang kamu sebut | Butuh kontrol penuh, grup non-hierarkis |
Dua hal ini paling sering bikin hasil kelihatan aneh.
ROLLUP(tahun, bulan) beda hasil dari ROLLUP(bulan, tahun). Taruh kolom level tertinggi di kiri.Satu catatan: kalau data kamu sendiri punya NULL, GROUPING() jadi satu-satunya cara aman bedain NULL subtotal dari NULL asli.
ROLLUP dan CUBE ngubah laporan multi-level jadi satu query ringkas. Yang perlu kamu bawa:
Mau query agregasi kayak gini jadi kebiasaan? Latihan langsung di NgulikSQL sambil ngerjain data beneran. Referensi sintaks resmi ada di dokumentasi PostgreSQL GROUPING SETS, CUBE, ROLLUP. Lanjut baca conditional aggregation dengan CASE 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.