GROUP BY: Merangkum per Kelompok (Laporan Mulai Terasa Nyata)
Mengelompokkan baris dengan GROUP BY lalu menghitung agregat per kelompok: jumlah produk per kategori, penjualan per bulan, dan aturan kolom yang boleh muncul di SELECT.
"Berapa per kategori?" adalah pertanyaan khas laporan
Agregat tanpa GROUP BY memberi satu angka untuk seluruh tabel. Bagaimana bila bos bertanya: "Berapa jumlah produk di tiap kategori?" Kita butuh satu angka per kelompok. Caranya:
SELECT kategori_id, COUNT(*) AS jumlah_produk, SUM(stok) AS total_stok
FROM produk
GROUP BY kategori_id;
+-------------+---------------+------------+
| kategori_id | jumlah_produk | total_stok |
+-------------+---------------+------------+
| NULL | 1 | 100 |
| 1 | 4 | 195 |
| 2 | 3 | 45 |
| 3 | 3 | 115 |
| 4 | 2 | 22 |
+-------------+---------------+------------+
Bayangkan prosesnya seperti menyortir kartu
- MySQL mengumpulkan semua baris, lalu menumpuknya ke dalam kelompok berdasarkan nilai kolom GROUP BY (satu tumpukan per kategori).
- Untuk setiap tumpukan, fungsi agregat dihitung.
- Hasilnya: satu baris per kelompok.
Seperti membagi uang receh ke beberapa gelas berdasarkan nominal, lalu menghitung isi tiap gelas. Baris dengan nilai NULL membentuk kelompok sendiri (lihat baris pertama di atas: produk tanpa kategori).
Aturan paling penting
Kolom di SELECT hanya boleh berupa: (1) kolom yang ada di GROUP BY, atau (2) fungsi agregat. Kolom lain tidak jelas nilainya (harga yang mana dari satu kelompok?), dan MySQL modern menolaknya dengan error "... isn't in GROUP BY" (mode ONLY_FULL_GROUP_BY).
-- SALAH: nama tidak ada di GROUP BY dan bukan agregat
SELECT kategori_id, nama, COUNT(*) FROM produk GROUP BY kategori_id;
Mengelompokkan dengan banyak kolom
SELECT kota, YEAR(tgl_daftar) AS tahun, COUNT(*) AS jumlah
FROM pelanggan
GROUP BY kota, YEAR(tgl_daftar);
Setiap kombinasi unik kota+tahun menjadi satu kelompok.
Mengelompokkan berdasarkan hasil fungsi
-- jumlah pesanan per bulan
SELECT DATE_FORMAT(tanggal, '%Y-%m') AS bulan, COUNT(*) AS jumlah_pesanan
FROM pesanan
GROUP BY DATE_FORMAT(tanggal, '%Y-%m')
ORDER BY bulan;
Menyusun hasil
Gabungkan dengan ORDER BY dan LIMIT untuk peringkat: "3 kategori dengan stok terbanyak" = GROUP BY ... ORDER BY total_stok DESC LIMIT 3. Dan ORDER BY boleh memakai agregat/alias langsung.
Urutan klausa lengkap sejauh ini
SELECT ... FROM ... WHERE ... GROUP BY ... ORDER BY ... LIMIT ...
Ingat: WHERE menyaring baris sebelum dikelompokkan. Menyaring kelompok setelah dihitung adalah tugas HAVING (bab berikutnya).