
Foto oleh panumas nikhomkhai via Pexels
GROUP BY digunakan ketika kita perlu meringkas data berdasarkan kategori tertentu, misalnya total penjualan per kota atau jumlah pesanan per pelanggan. Tanpa GROUP BY, setiap baris data mentah harus diproses satu per satu di sisi aplikasi untuk mendapatkan ringkasan semacam ini — pekerjaan yang jauh lebih efisien dilakukan langsung di database.
Artikel ini membahas cara kerja GROUP BY beserta aturan penting yang sering membingungkan pemula, terutama terkait kolom apa saja yang boleh muncul di SELECT ketika GROUP BY dipakai.
Sintaks Dasar GROUP BY
Menghitung jumlah customer per kota
GROUP BY mengelompokkan baris-baris yang memiliki nilai sama pada kolom yang disebutkan, lalu setiap kelompok diringkas menjadi satu baris hasil menggunakan fungsi agregat seperti COUNT, SUM, atau AVG.
Aturan Penting: Kolom di SELECT Harus Ada di GROUP BY
Kolom non-agregat wajib disertakan di GROUP BY
SQL Server akan menolak query jika ada kolom di SELECT yang bukan hasil fungsi agregat namun tidak disebutkan di GROUP BY, karena SQL Server tidak tahu nilai mana yang harus dipilih untuk mewakili kelompok tersebut jika satu City punya banyak Province berbeda.
GROUP BY dengan Banyak Kolom Agregat
Ringkasan lengkap per pelanggan
Satu query GROUP BY bisa menghasilkan banyak kolom ringkasan sekaligus, menjadikannya cara paling efisien membuat laporan dashboard dibanding menjalankan beberapa query terpisah untuk setiap metrik.
GROUP BY pada Ekspresi, Bukan Hanya Kolom Mentah
GROUP BY berdasarkan hasil ekspresi, bukan kolom asli
GROUP BY tidak terbatas pada kolom mentah — ekspresi seperti hasil fungsi YEAR() dan MONTH() juga bisa dipakai, sangat berguna untuk laporan ringkasan per periode waktu tanpa perlu kolom tambahan khusus di table.
Menggunakan GROUP BY dengan Lebih dari Satu Kolom
GROUP BY dengan kombinasi dua kolom
Saat GROUP BY diberi lebih dari satu kolom, SQL Server akan memperlakukan setiap kombinasi unik dari kolom-kolom tersebut sebagai satu kelompok tersendiri. Ini berbeda dengan anggapan keliru bahwa menambahkan kolom kedua hanya menambah detail di dalam kelompok yang sudah ada — sebenarnya jumlah barisnya bisa jauh lebih banyak karena setiap kombinasi dihitung terpisah.
Urutan kolom dalam GROUP BY tidak memengaruhi hasil pengelompokan secara logis, namun tetap memengaruhi urutan default penyajian data sebelum ORDER BY diterapkan. Praktik yang aman adalah selalu menambahkan ORDER BY eksplisit setelah GROUP BY multi-kolom agar urutan tampilan tidak bergantung pada perilaku internal mesin database yang bisa berubah antar versi.
Aturan Kolom pada SELECT Saat Memakai GROUP BY
Error umum saat kolom non-agregat tidak disertakan di GROUP BY
Ketika sebuah query memakai GROUP BY, SQL Server mewajibkan setiap kolom yang muncul di klausa SELECT untuk berupa salah satu dari dua hal saja: kolom yang juga disebutkan di GROUP BY, atau kolom yang dibungkus di dalam fungsi agregat seperti SUM, COUNT, AVG, MIN, atau MAX. Aturan ini masuk akal secara logis karena GROUP BY meringkas banyak baris menjadi satu baris per kelompok, sehingga SQL Server perlu tahu persis bagaimana cara meringkas setiap kolom yang ditampilkan.
Mencoba menampilkan kolom seperti ProductName tanpa fungsi agregat padahal GROUP BY hanya dilakukan pada Category akan menghasilkan error, karena dalam satu kelompok Category yang sama bisa terdapat banyak ProductName berbeda, dan SQL Server tidak memiliki cara otomatis untuk memutuskan ProductName mana yang harus ditampilkan mewakili kelompok tersebut.
GROUP BY sendiri secara logis dieksekusi setelah WHERE namun sebelum SELECT dan ORDER BY dalam urutan pemrosesan query, artinya kondisi WHERE menyaring baris mentah terlebih dahulu sebelum pengelompokan terjadi, sementara penyaringan terhadap hasil agregat setelah pengelompokan harus memakai HAVING, bukan WHERE.
GROUPING SETS dan ROLLUP untuk Subtotal Bertingkat
ROLLUP menghasilkan subtotal dan grand total otomatis
GROUPING SETS adalah perluasan GROUP BY yang memungkinkan satu query menghasilkan beberapa level agregasi sekaligus dalam satu hasil, menggantikan kebutuhan menulis beberapa query terpisah yang digabung dengan UNION ALL. Dengan GROUPING SETS (Kota, Kategori), (Kota), () misalnya, SQL Server akan menghasilkan baris agregasi per kombinasi Kota-Kategori, per Kota saja, dan satu baris grand total, semuanya dalam satu kali pemindaian data.
ROLLUP adalah bentuk singkat dari GROUPING SETS untuk kasus hierarki berjenjang yang umum, seperti Kota lalu Kategori di dalamnya, yang secara otomatis menghasilkan subtotal pada setiap level hierarki ditambah satu grand total di baris terakhir. Baris subtotal ini ditandai dengan nilai NULL pada kolom yang sedang diringkas, namun NULL ini bisa membingungkan jika data asli memang mengandung NULL, sehingga fungsi GROUPING() disediakan untuk membedakan NULL hasil ROLLUP dari NULL data asli.
Pemakaian ROLLUP dan GROUPING SETS sangat relevan untuk laporan keuangan atau laporan manajemen yang membutuhkan tampilan bertingkat seperti subtotal per cabang dan total perusahaan dalam satu laporan, tanpa perlu memproses ulang data di sisi aplikasi. Dibanding menggabungkan beberapa query manual dengan UNION ALL, pendekatan ini lebih efisien karena SQL Server dapat mengoptimalkan seluruh level agregasi dalam satu rencana eksekusi, bukan menjalankan pemindaian table berulang kali untuk setiap level.
GROUP BY dengan Ekspresi Tanggal untuk Agregasi per Bulan
GROUP BY berdasarkan ekspresi tanggal
GROUP BY tidak hanya bisa mengelompokkan berdasarkan kolom asli, melainkan juga berdasarkan ekspresi yang dihitung dari kolom tersebut, seperti YEAR(TanggalPesan) dan MONTH(TanggalPesan) untuk mengelompokkan data transaksi ke dalam periode tahun dan bulan. Ekspresi yang sama persis dengan yang ditulis di SELECT harus pula dituliskan di GROUP BY, karena SQL Server memperlakukan keduanya sebagai satu kesatuan definisi kelompok.
Pendekatan ini banyak dipakai untuk laporan tren bulanan atau tahunan tanpa perlu kolom tambahan khusus periode pada table sumber. Namun perlu diperhatikan bahwa membungkus kolom tanggal dengan fungsi seperti YEAR dan MONTH membuat GROUP BY tidak lagi SARGable terhadap index pada kolom tanggal tersebut, sehingga pada table dengan jutaan baris, pendekatan rentang tanggal eksplisit kadang lebih efisien dibanding mengandalkan fungsi langsung di dalam GROUP BY.
Kesalahan Umum yang Sering Terjadi
Mengira bisa memilih kolom bebas asal ada GROUP BY di query
Pemula sering mengira GROUP BY pada satu kolom mengizinkan kolom lain muncul bebas di SELECT, padahal SQL Server akan selalu menolak kolom non-agregat yang tidak disebutkan di GROUP BY.
Lupa bahwa GROUP BY pada ekspresi harus menulis ulang ekspresi yang sama persis
GROUP BY YEAR(OrderDate) tidak otomatis mengenali alias Tahun yang didefinisikan di SELECT pada beberapa versi SQL Server, sehingga ekspresi aslinya perlu ditulis ulang di GROUP BY.
Kapan Pendekatan Ini Tidak Cocok Dipakai
GROUP BY pada kolom dengan kardinalitas sangat tinggi (misalnya mengelompokkan berdasarkan CustomerId pada tabel dengan jutaan pelanggan) bisa menghasilkan jutaan baris hasil ringkasan yang hampir sama beratnya dengan data mentah, sehingga manfaat 'meringkas' menjadi kurang terasa dibanding mengelompokkan berdasarkan kolom dengan variasi nilai yang lebih sedikit.
Ringkasan
GROUP BY adalah fondasi untuk membuat laporan ringkas dari data mentah. Memahami aturan kolom non-agregat sejak awal akan mencegah error yang sering membingungkan pemula ketika pertama kali belajar agregasi data.
Kombinasi GROUP BY dengan ekspresi seperti YEAR() dan MONTH() membuka banyak kemungkinan laporan periodik yang sangat umum dibutuhkan di hampir setiap aplikasi bisnis.
Seri Belajar SQL Server:
← Sebelumnya: Memahami LEFT JOIN RIGHT JOIN dan FULL JOIN
→ Selanjutnya: Filtering Hasil Group dengan HAVING