Fungsi GROUP BY dan HAVING di SQL: Panduan Lengkap
Blog/Tutorial SQL/Fungsi GROUP BY dan HAVING di SQL: Panduan Lengkap

Fungsi GROUP BY dan HAVING di SQL: Panduan Lengkap

BimaBima
·22 Desember 2025·12 menit baca

Penulis

Bima

Bima

Founder & Data Professional

Bagikan

Terakhir diperbarui: 22 Desember 2025

TL;DR

GROUP BY buat mengelompokkan data berdasarkan kolom tertentu, HAVING buat filter hasil agregasi. WHERE filter sebelum grouping, HAVING filter sesudah.

Apa Itu GROUP BY di SQL?

Pernah bingung gimana caranya ngitung total penjualan per provinsi? Atau pengen tau rata-rata order per kategori produk? Nah, di sinilah GROUP BY jadi penyelamat kamu.

GROUP BY itu perintah SQL yang dipakai buat mengelompokkan baris data berdasarkan satu atau lebih kolom. Setelah dikelompokkan, kamu bisa pakai fungsi agregasi kayak SUM, COUNT, AVG, MAX, atau MIN untuk ngitung sesuatu dari tiap kelompok.

Bayangin kamu punya tumpukan nota penjualan. Terus kamu mau pisahin berdasarkan provinsi, dan hitung total penjualan masing-masing. Itulah basically yang GROUP BY lakuin.

Kenapa GROUP BY Penting Banget?

Sebagai Data Analyst, kamu pasti sering banget dapet request kayak gini:

  • "Berapa total penjualan per bulan?"
  • "Produk mana yang paling laku di tiap provinsi?"
  • "Rata-rata nilai order per kategori berapa sih?"

Semua pertanyaan itu butuh GROUP BY. Tanpa GROUP BY, kamu cuma bisa dapet satu angka total dari seluruh data. Tapi dengan GROUP BY, kamu bisa breakdown datanya jadi insight yang lebih meaningful.

Dataset yang Akan Kita Pakai

Buat tutorial ini, kita pakai dataset penjualan UMKM Indonesia. Bayangin kamu jadi Data Analyst di platform marketplace yang bantu UMKM jualan online.

Tabel: penjualan

id tanggal provinsi kategori produk qty harga_satuan total
1 2024-01-15 Jawa Barat Makanan Keripik Singkong 50 15000 750000
2 2024-01-15 Jawa Tengah Kerajinan Batik Tulis 5 250000 1250000
3 2024-01-16 Jawa Barat Makanan Dodol Garut 30 25000 750000
4 2024-01-16 Bali Kerajinan Ukiran Kayu 3 500000 1500000
5 2024-01-17 Jawa Barat Fashion Kaos Distro 20 85000 1700000
6 2024-01-17 Jawa Tengah Makanan Lumpia Semarang 40 20000 800000
7 2024-01-18 Bali Makanan Pie Susu 100 8000 800000
8 2024-01-18 Yogyakarta Kerajinan Perak Kotagede 10 150000 1500000
9 2024-01-19 Jawa Barat Makanan Keripik Singkong 60 15000 900000
10 2024-01-19 Jawa Tengah Fashion Batik Cap 15 120000 1800000

Tabel: umkm

id nama_usaha provinsi kategori tahun_berdiri
1 Keripik Bu Siti Jawa Barat Makanan 2018
2 Batik Sekar Jawa Tengah Kerajinan 2015
3 Dodol Pak Asep Jawa Barat Makanan 2020
4 Bali Craft Bali Kerajinan 2019
5 Urban Threads Jawa Barat Fashion 2021

Sintaks Dasar GROUP BY

Ini struktur dasar GROUP BY:

SELECT kolom_grouping, FUNGSI_AGREGASI(kolom)
FROM nama_tabel
WHERE kondisi
GROUP BY kolom_grouping;

Yang perlu kamu inget:
1. Kolom yang muncul di SELECT (yang bukan fungsi agregasi) HARUS ada di GROUP BY
2. GROUP BY dijalankan SETELAH WHERE
3. Kamu bisa GROUP BY lebih dari satu kolom

Contoh 1: Total Penjualan per Provinsi

Ini contoh paling basic. Kita mau tau total penjualan di tiap provinsi.

SELECT
    provinsi,
    SUM(total) AS total_penjualan
FROM penjualan
GROUP BY provinsi;

Hasil:

provinsi total_penjualan
Jawa Barat 4100000
Jawa Tengah 3850000
Bali 2300000
Yogyakarta 1500000

Keren kan? Dengan satu query, kamu bisa langsung liat provinsi mana yang penjualannya paling gede.

Contoh 2: Jumlah Transaksi dan Rata-rata per Kategori

Sekarang kita mau liat performa tiap kategori produk.

SELECT
    kategori,
    COUNT(*) AS jumlah_transaksi,
    SUM(total) AS total_penjualan,
    AVG(total) AS rata_rata_order
FROM penjualan
GROUP BY kategori;

Hasil:

kategori jumlah_transaksi total_penjualan rata_rata_order
Makanan 5 4000000 800000
Kerajinan 3 4250000 1416667
Fashion 2 3500000 1750000

Dari sini keliatan bahwa walaupun Makanan punya transaksi paling banyak, tapi rata-rata nilai ordernya paling kecil. Sementara Fashion punya rata-rata order tertinggi.

Contoh 3: GROUP BY dengan Multiple Columns

Kamu juga bisa grouping berdasarkan lebih dari satu kolom. Misalnya, kita mau liat penjualan per provinsi DAN per kategori.

SELECT
    provinsi,
    kategori,
    SUM(total) AS total_penjualan
FROM penjualan
GROUP BY provinsi, kategori
ORDER BY provinsi, total_penjualan DESC;

Hasil:

provinsi kategori total_penjualan
Bali Kerajinan 1500000
Bali Makanan 800000
Jawa Barat Fashion 1700000
Jawa Barat Makanan 2400000
Jawa Tengah Fashion 1800000
Jawa Tengah Kerajinan 1250000
Jawa Tengah Makanan 800000
Yogyakarta Kerajinan 1500000

Nah, sekarang kamu bisa liat breakdown yang lebih detail. Jawa Barat ternyata paling kuat di kategori Makanan.

Apa Itu HAVING?

Oke, sekarang bayangin kamu mau filter hasil GROUP BY. Misalnya, kamu cuma mau liat provinsi yang total penjualannya di atas 2 juta.

Banyak yang mikir, "Ya udah pake WHERE aja dong!"

Tapi tunggu dulu. WHERE itu filter SEBELUM data di-group. Jadi kamu ga bisa nulis kayak gini:

-- INI SALAH!
SELECT provinsi, SUM(total) AS total_penjualan
FROM penjualan
WHERE SUM(total) > 2000000  -- Error!
GROUP BY provinsi;

Query di atas bakal error karena WHERE ga bisa pake fungsi agregasi. Di sinilah HAVING masuk.

HAVING itu filter yang dijalankan SETELAH GROUP BY. Jadi kamu bisa filter berdasarkan hasil agregasi.

Sintaks HAVING

SELECT kolom_grouping, FUNGSI_AGREGASI(kolom)
FROM nama_tabel
WHERE kondisi_per_baris
GROUP BY kolom_grouping
HAVING kondisi_agregasi;

Urutan eksekusi:
1. FROM - ambil data dari tabel
2. WHERE - filter baris individual
3. GROUP BY - kelompokkan data
4. HAVING - filter hasil grouping
5. SELECT - pilih kolom yang mau ditampilkan
6. ORDER BY - urutkan hasil

Contoh 4: HAVING untuk Filter Agregasi

Sekarang kita coba filter provinsi dengan total penjualan di atas 2 juta.

SELECT
    provinsi,
    SUM(total) AS total_penjualan
FROM penjualan
GROUP BY provinsi
HAVING SUM(total) > 2000000;

Hasil:

provinsi total_penjualan
Jawa Barat 4100000
Jawa Tengah 3850000
Bali 2300000

Yogyakarta ga masuk karena total penjualannya cuma 1.5 juta.

Contoh 5: Kombinasi WHERE dan HAVING

Ini yang sering bikin bingung. Kapan pake WHERE, kapan pake HAVING?

Inget aturan ini:
- WHERE: filter baris SEBELUM grouping (filter per record)
- HAVING: filter SETELAH grouping (filter hasil agregasi)

Misalnya, kamu mau liat total penjualan per kategori, tapi:
1. Cuma untuk transaksi di bulan Januari 2024
2. Dan cuma kategori yang total penjualannya di atas 1 juta

SELECT
    kategori,
    SUM(total) AS total_penjualan
FROM penjualan
WHERE tanggal BETWEEN '2024-01-01' AND '2024-01-31'
GROUP BY kategori
HAVING SUM(total) > 1000000;

Hasil:

kategori total_penjualan
Makanan 4000000
Kerajinan 4250000
Fashion 3500000

Di sini, WHERE filter dulu transaksi yang di Januari, baru di-group dan difilter pake HAVING.

Contoh 6: HAVING dengan COUNT

HAVING juga sering dipake bareng COUNT. Misalnya, kamu mau cari provinsi yang punya minimal 3 transaksi.

SELECT
    provinsi,
    COUNT(*) AS jumlah_transaksi
FROM penjualan
GROUP BY provinsi
HAVING COUNT(*) >= 3;

Hasil:

provinsi jumlah_transaksi
Jawa Barat 4
Jawa Tengah 3

Bali dan Yogyakarta ga masuk karena transaksinya kurang dari 3.

Contoh 7: Multiple Conditions di HAVING

Kamu bisa pakai AND dan OR di HAVING, sama kayak di WHERE.

SELECT
    kategori,
    COUNT(*) AS jumlah_transaksi,
    SUM(total) AS total_penjualan,
    AVG(total) AS rata_rata
FROM penjualan
GROUP BY kategori
HAVING COUNT(*) >= 2 AND AVG(total) > 1000000;

Hasil:

kategori jumlah_transaksi total_penjualan rata_rata
Kerajinan 3 4250000 1416667
Fashion 2 3500000 1750000

Query ini cari kategori yang punya minimal 2 transaksi DAN rata-rata order di atas 1 juta.

Contoh 8: GROUP BY dengan Date Functions

Ini sering banget dipake buat bikin laporan periodik. Misalnya, total penjualan per minggu.

SELECT
    DATE_TRUNC('week', tanggal) AS minggu,
    SUM(total) AS total_penjualan
FROM penjualan
GROUP BY DATE_TRUNC('week', tanggal)
ORDER BY minggu;

Atau kalau kamu mau per bulan:

SELECT
    EXTRACT(YEAR FROM tanggal) AS tahun,
    EXTRACT(MONTH FROM tanggal) AS bulan,
    SUM(total) AS total_penjualan
FROM penjualan
GROUP BY
    EXTRACT(YEAR FROM tanggal),
    EXTRACT(MONTH FROM tanggal)
ORDER BY tahun, bulan;

Contoh 9: GROUP BY dengan JOIN

Sekarang kita gabungin tabel penjualan dengan tabel umkm. Misalnya, kita mau tau total penjualan per tahun berdiri UMKM.

SELECT
    u.tahun_berdiri,
    COUNT(DISTINCT u.id) AS jumlah_umkm,
    SUM(p.total) AS total_penjualan
FROM penjualan p
JOIN umkm u ON p.provinsi = u.provinsi AND p.kategori = u.kategori
GROUP BY u.tahun_berdiri
ORDER BY u.tahun_berdiri;

Ini bisa ngasih insight menarik, misalnya UMKM yang udah lama berdiri penjualannya gimana dibanding yang baru.

Common Mistakes yang Harus Dihindari

Mistake 1: Kolom Non-Agregat ga Ada di GROUP BY

-- SALAH
SELECT provinsi, kategori, SUM(total)
FROM penjualan
GROUP BY provinsi;  -- kategori ga di-include

Ini bakal error. Semua kolom yang bukan fungsi agregasi HARUS ada di GROUP BY.

Mistake 2: Pake WHERE untuk Filter Agregasi

-- SALAH
SELECT provinsi, SUM(total)
FROM penjualan
WHERE SUM(total) > 1000000  -- Error!
GROUP BY provinsi;

Pake HAVING, bukan WHERE, untuk filter hasil agregasi.

Mistake 3: Salah Urutan Clause

-- SALAH
SELECT provinsi, SUM(total)
FROM penjualan
HAVING SUM(total) > 1000000
GROUP BY provinsi;  -- HAVING sebelum GROUP BY

Urutan yang bener: SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY.

Mistake 4: Lupa NULL Values

NULL itu dikelompokkan jadi satu grup tersendiri. Kadang ini bikin hasil query jadi unexpected. Pake COALESCE kalau perlu handle NULL.

SELECT
    COALESCE(provinsi, 'Tidak Diketahui') AS provinsi,
    SUM(total) AS total_penjualan
FROM penjualan
GROUP BY provinsi;

Tips Praktis buat Data Analyst

1. Aliasing Hasil Agregasi

Selalu kasih alias yang descriptive ke hasil agregasi. Ini bikin query lebih readable dan hasilnya lebih gampang dipahami.

SELECT
    kategori,
    SUM(total) AS total_pendapatan,
    AVG(total) AS rata_rata_transaksi,
    MAX(total) AS transaksi_terbesar
FROM penjualan
GROUP BY kategori;

2. Pake ORDER BY buat Sorting

Hasil GROUP BY biasanya lebih berguna kalau di-sort.

SELECT
    provinsi,
    SUM(total) AS total_penjualan
FROM penjualan
GROUP BY provinsi
ORDER BY total_penjualan DESC;  -- Dari yang terbesar

3. ROUND untuk Angka Decimal

Rata-rata sering menghasilkan angka decimal panjang. Pake ROUND biar lebih clean.

SELECT
    kategori,
    ROUND(AVG(total), 2) AS rata_rata
FROM penjualan
GROUP BY kategori;

4. Combine dengan CASE WHEN

Kamu bisa bikin grouping yang lebih custom pake CASE WHEN.

SELECT
    CASE
        WHEN total < 1000000 THEN 'Small'
        WHEN total < 2000000 THEN 'Medium'
        ELSE 'Large'
    END AS order_size,
    COUNT(*) AS jumlah
FROM penjualan
GROUP BY
    CASE
        WHEN total < 1000000 THEN 'Small'
        WHEN total < 2000000 THEN 'Medium'
        ELSE 'Large'
    END;

Kapan Pake GROUP BY vs Subquery?

Kadang ada yang bingung, mending pake GROUP BY atau subquery. Aturan simpelnya:

  • GROUP BY: Kalau kamu mau agregasi dan tampilin hasilnya langsung
  • Subquery: Kalau hasil agregasi mau dipake buat filter atau join dengan data lain

Contoh pake subquery:

-- Cari transaksi yang nilainya di atas rata-rata
SELECT *
FROM penjualan
WHERE total > (
    SELECT AVG(total) FROM penjualan
);

Kesimpulan

Nah, sekarang kamu udah paham kan gimana caranya pake GROUP BY dan HAVING? Inget poin-poin ini:

  1. GROUP BY mengelompokkan data berdasarkan kolom tertentu
  2. HAVING filter hasil agregasi (setelah GROUP BY)
  3. WHERE filter baris individual (sebelum GROUP BY)
  4. Semua kolom non-agregat di SELECT HARUS ada di GROUP BY
  5. Urutan: FROM > WHERE > GROUP BY > HAVING > SELECT > ORDER BY

Latihan itu kunci. Coba bikin query sendiri pake dataset yang kamu punya. Mulai dari yang simple kayak COUNT dan SUM per kategori, terus lanjut ke yang lebih kompleks.

Happy querying! Kalau ada pertanyaan, langsung aja praktek di nguliksql.id ya!

Bagikan:
Bima
Ditulis oleh

Bima

Founder & Data Professional

Founder Ngulik Data. Passionate about making data analysis accessible for everyone.

Artikel Terkait

Cara Menggunakan Subquery di SQL (Dengan 10 Contoh Praktis)
Tutorial SQL
21 Desember 2025•14 menit baca

Cara Menggunakan Subquery di SQL (Dengan 10 Contoh Praktis)

Pelajari cara pakai subquery di SQL dengan 10 contoh praktis menggunakan dataset e-commerce Indonesia

BimaBima
Perbedaan INNER JOIN, LEFT JOIN, RIGHT JOIN, dan FULL JOIN di SQL
Tutorial SQL
19 Desember 2025•12 menit baca

Perbedaan INNER JOIN, LEFT JOIN, RIGHT JOIN, dan FULL JOIN di SQL

Belajar perbedaan jenis-jenis JOIN di SQL dengan contoh praktis dan visualisasi. Panduan lengkap INNER, LEFT, RIGHT, dan FULL JOIN untuk pemula.

BimaBima
Cara Install PostgreSQL di Windows, Mac, dan Linux (Panduan Lengkap)
Tutorial SQL
19 Desember 2025•12 menit baca

Cara Install PostgreSQL di Windows, Mac, dan Linux (Panduan Lengkap)

Panduan step-by-step install PostgreSQL di Windows, macOS, dan Linux lengkap dengan pgAdmin dan troubleshooting

BimaBima
Kembali ke Blog
Ngulik Data logoNgulik Data

Platform edukasi data lengkap untuk professionals Indonesia. Belajar SQL, Data Analysis, dan lebih banyak lagi dengan praktek langsung dan feedback real-time.

Copyright © 2026 - All rights reserved

LINKS
SupportPricingBlogAffiliates
LEGAL
Terms of servicesPrivacy policy