Fungsi Agregat SQL: COUNT, SUM, AVG, MIN, MAX dalam 1 Panduan
Blog/Tutorial SQL/Fungsi Agregat SQL: COUNT, SUM, AVG, MIN, MAX dalam 1 Panduan

Fungsi Agregat SQL: COUNT, SUM, AVG, MIN, MAX dalam 1 Panduan

BimaBima
·27 Januari 2026·9 menit baca

Penulis

Bima

Bima

Founder & Data Professional

Bagikan

TL;DR

Fungsi agregat SQL adalah fungsi yang meringkas banyak baris jadi satu angka: COUNT (hitung baris), SUM (total), AVG (rata-rata), MIN (nilai terkecil), dan MAX (nilai terbesar). Semuanya dipakai di klausa SELECT dan biasanya digabung sama GROUP BY buat ngitung per kelompok. Kecuali COUNT(*), semua fungsi agregat ngelewatin baris yang nilainya NULL.

Fungsi agregat SQL adalah fungsi yang meringkas banyak baris jadi satu angka. Sepuluh ribu transaksi masuk, satu angka omzet keluar.

Ada lima yang standar dan ada di semua database: COUNT, SUM, AVG, MIN, MAX. Kuasain lima ini dan kamu udah bisa bikin 80% laporan yang diminta kantor.

Contoh di sini pakai tabel transaksi toko_berkah: 10 baris, 3 kota, dan kolom rating yang sengaja ada NULL-nya — soalnya gak semua pelanggan ngasih rating.

Apa itu fungsi agregat di SQL?

Fungsi agregat adalah fungsi yang ngambil banyak baris sebagai input dan ngeluarin satu nilai sebagai output. Ditulis di klausa SELECT, dan biasanya dipasangin sama GROUP BY.

FungsiKerjanyaContoh pertanyaan bisnis
COUNTHitung jumlah barisAda berapa transaksi bulan ini?
SUMJumlahkan nilaiBerapa total omzetnya?
AVGRata-rataRata-rata belanja per struk berapa?
MINNilai terkecilTransaksi paling kecil berapa?
MAXNilai terbesarTransaksi paling gede berapa?

Kelimanya bisa dipakai bareng dalam satu query:

SELECT COUNT(*)           AS jumlah_transaksi,
       SUM(total_belanja) AS total_omzet,
       AVG(total_belanja) AS rata_rata_belanja,
       MIN(total_belanja) AS belanja_terkecil,
       MAX(total_belanja) AS belanja_terbesar
FROM transaksi;
jumlah_transaksitotal_omzetrata_rataterkecilterbesar
101.420.500142.05045.000310.000

Sepuluh baris jadi satu baris. Tanpa GROUP BY, seluruh tabel dianggap satu kelompok besar.

Daftar resmi fungsi agregat ada di dokumentasi aggregate functions PostgreSQL.

Gimana cara pakai COUNT di SQL?

COUNT punya tiga bentuk, dan tiga-tiganya ngasih angka beda:

SELECT COUNT(*)                     AS semua_baris,
       COUNT(rating)                AS rating_terisi,
       COUNT(DISTINCT id_pelanggan) AS pelanggan_unik
FROM transaksi;

Hasil: 10 | 7 | 6
  • COUNT(*) — hitung semua baris, gak peduli isinya. Hasilnya 10.
  • COUNT(rating) — hitung baris yang rating-nya gak NULL. Hasilnya 7, soalnya 3 transaksi gak dikasih rating.
  • COUNT(DISTINCT id_pelanggan) — hitung pelanggan unik. Hasilnya 6, walaupun ada 10 transaksi.

Beda 10 versus 6 itu penting banget. "Ada 10 transaksi" dan "ada 10 pelanggan" itu dua klaim yang jauh beda, dan salah pilih COUNT bikin kamu ngasih angka salah ke bos.

Detail COUNT lengkapnya ada di halaman fungsi COUNT.

Gimana cara pakai SUM dan AVG?

SUM jumlahin isi kolom. AVG rata-ratain.

SELECT SUM(total_belanja) AS total_omzet,
       AVG(total_belanja) AS rata_rata
FROM transaksi;

Hasil: 1.420.500 | 142.050

Dua-duanya cuma jalan di kolom angka. Nyoba SUM(kota) bakal langsung error.

AVG suka ngasih desimal panjang. Bungkus pakai ROUND biar rapi:

SELECT ROUND(AVG(total_belanja), 0) AS rata_rata_bulat
FROM transaksi;

Argumen SUM selengkapnya ada di halaman fungsi SUM.

Gimana cara pakai MIN dan MAX?

MIN ngambil nilai terkecil, MAX terbesar. Bedanya sama SUM dan AVG: dua fungsi ini juga jalan di kolom teks dan tanggal.

SELECT MIN(tgl_transaksi) AS transaksi_pertama,
       MAX(tgl_transaksi) AS transaksi_terakhir,
       MIN(kota)          AS kota_pertama_alfabet
FROM transaksi;

Hasil: 2026-01-05 | 2026-01-24 | Bandung

MIN dan MAX di kolom tanggal itu senjata buat ngitung rentang aktivitas pelanggan — kapan dia pertama beli, kapan terakhir muncul.

Satu hal yang sering bikin salah paham: MAX(total_belanja) ngasih kamu angka transaksi terbesar, tapi gak ngasih tau siapa pelakunya. Buat itu kamu butuh subquery atau window function — topik terpisah.

Gimana bikin agregat per kelompok pakai GROUP BY?

Angka total doang jarang cukup. Yang ditanya bos biasanya: "per kota berapa?"

SELECT kota,
       COUNT(*)                     AS jumlah_transaksi,
       COUNT(DISTINCT id_pelanggan) AS pelanggan_unik,
       SUM(total_belanja)           AS total_omzet,
       ROUND(AVG(total_belanja), 0) AS rata_rata,
       MAX(total_belanja)           AS transaksi_terbesar
FROM transaksi
GROUP BY kota
ORDER BY total_omzet DESC;
kotatransaksipelanggan unikomzetrata-rataterbesar
Bandung53868.500173.700310.000
Surabaya32419.000139.667199.000
Semarang21133.00066.50088.000

Aturan wajibnya cuma satu: tiap kolom di SELECT harus ikut di GROUP BY, atau dibungkus fungsi agregat. Nulis SELECT kota, tgl_transaksi, SUM(...) tanpa masukin tgl_transaksi ke GROUP BY bakal error — database gak tau harus nampilin tanggal yang mana dari 5 baris Bandung.

Apa bedanya WHERE dan HAVING?

WHERE nyaring baris, sebelum dikelompokin. HAVING nyaring grup, setelah dihitung.

SELECT kota,
       SUM(total_belanja) AS total_omzet
FROM transaksi
WHERE tgl_transaksi >= '2026-01-10'   -- saring baris dulu
GROUP BY kota
HAVING SUM(total_belanja) > 300000    -- baru saring grupnya
ORDER BY total_omzet DESC;

Coba tulis WHERE SUM(total_belanja) > 300000 dan kamu bakal langsung kena error. Waktu WHERE jalan, SUM-nya belum ada — belum ada grup yang dijumlahin.

Urutan eksekusinya: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY.

Tips performa: taruh kondisi biasa di WHERE, jangan di HAVING. Makin sedikit baris yang masuk ke GROUP BY, makin ringan kerjaan database.

Gimana fungsi agregat memperlakukan NULL?

Ini yang paling sering bikin angka laporan salah diam-diam.

Semua fungsi agregat ngelewatin NULL — kecuali COUNT(*).

SELECT AVG(rating)                  AS avg_rating,   -- 4.0
       SUM(rating) * 1.0 / COUNT(*) AS versi_salah   -- 2.8
FROM transaksi;

Total rating = 28. Baris yang ada rating-nya = 7. Total baris = 10.

AVG bagi 28 dengan 7 → 4,0. Kalau kamu ngitung manual pakai SUM/COUNT(*), kamu bagi 28 dengan 10 → 2,8.

Selisih 4,0 versus 2,8 itu gede. Satu bilang pelanggan puas, satu bilang biasa aja. Dan dua-duanya "benar" — tergantung kamu mau jawab pertanyaan yang mana: rata-rata rating dari yang ngasih rating, atau rata-rata rating dari semua transaksi (nganggep yang gak ngasih rating = 0).

Yang bahaya itu kalau kamu gak sadar bedanya. Perilaku NULL lengkapnya ada di glosarium NULL.

Contoh kasus: cari repeat buyer toko_berkah

Bu Sari mau tau pelanggan mana yang balik lagi, dan berapa jarak antara pembelian pertama dan terakhir mereka.

SELECT id_pelanggan,
       COUNT(*)           AS jumlah_transaksi,
       SUM(total_belanja) AS total_belanja,
       MIN(tgl_transaksi) AS transaksi_pertama,
       MAX(tgl_transaksi) AS transaksi_terakhir
FROM transaksi
GROUP BY id_pelanggan
HAVING COUNT(*) > 1
ORDER BY total_belanja DESC;
pelanggantransaksitotalpertamaterakhir
13501.0002026-01-052026-01-18
22220.0002026-01-062026-01-15
62133.0002026-01-212026-01-24

Tiga dari enam pelanggan balik lagi. Pelanggan 1 belanja 3 kali dalam 13 hari, total Rp 501 ribu — sendirian nyumbang 35% dari total omzet Rp 1,42 juta.

Angka HAVING COUNT(*) > 1 itu yang misahin "pelanggan" dan "repeat buyer". Tanpa HAVING, kamu dapat daftar semua orang. Dengan HAVING, kamu dapat daftar orang yang layak dikasih diskon loyalitas.

Kesalahan umum pakai fungsi agregat

1. Nulis kolom biasa di SELECT tanpa masukin ke GROUP BY

SELECT kota, tgl_transaksi, SUM(total_belanja) FROM transaksi GROUP BY kota; bakal error di PostgreSQL. MySQL kadang ngizinin, dan itu justru lebih bahaya — dia bakal ngasih tanggal acak dari salah satu baris, dan kamu gak sadar.

2. Pakai WHERE buat nyaring hasil agregat

WHERE COUNT(*) > 1 selalu error. Kondisi yang ngelibatin fungsi agregat wajib di HAVING.

3. Ngira COUNT(*) sama dengan COUNT(kolom)

Bedanya cuma NULL, tapi selisihnya bisa bikin laporan salah. Kalau kamu mau tau "berapa transaksi", pakai COUNT(*). Kalau mau tau "berapa yang ngisi rating", pakai COUNT(rating).

4. COUNT(*) setelah LEFT JOIN

LEFT JOIN bikin pelanggan tanpa transaksi tetap muncul, dengan kolom transaksi berisi NULL. COUNT(*) bakal ngitung baris itu sebagai 1 — padahal transaksinya nol. Pakai COUNT(t.id_transaksi) biar NULL-nya dilewat dan hasilnya 0.

5. Rata-rata dari rata-rata

AVG dari kolom yang isinya udah rata-rata bakal ngasih angka salah, soalnya tiap grup punya jumlah baris beda. Rata-rata dari 3 kota bukan rata-rata nasional — kecuali tiap kota transaksinya sama banyak.

FAQ soal fungsi agregat SQL

Fungsi agregat bisa dipakai tanpa GROUP BY?

Bisa. Tanpa GROUP BY, seluruh tabel dianggap satu kelompok dan hasilnya satu baris. GROUP BY baru dibutuhin kalau kamu mau angka per kota, per bulan, atau per kategori.

Bisa gak nge-nest fungsi agregat?

SUM(AVG(total_belanja)) bakal error di kebanyakan database. Kalau kamu butuh agregat dari hasil agregat, bungkus lapisan pertamanya jadi subquery, terus agregasi lagi di lapisan luar.

Kenapa SUM hasilnya NULL, bukan 0?

Kalau gak ada satu pun baris yang lolos filter, SUM balikin NULL — bukan 0. Ini sering bikin laporan nampilin sel kosong. Bungkus pakai COALESCE: COALESCE(SUM(total_belanja), 0).

Selain lima itu, ada fungsi agregat lain?

Ada, tapi beda-beda per database. PostgreSQL punya STRING_AGG buat gabungin teks dan ARRAY_AGG. MySQL punya GROUP_CONCAT. Buat statistik ada STDDEV dan VARIANCE. Kuasain lima yang standar dulu — itu yang kepakai tiap hari.

Ringkasnya

COUNT ngitung, SUM njumlahin, AVG ngerata-ratain, MIN dan MAX nyari ujungnya. GROUP BY yang bikin semuanya jadi per kelompok.

Dua hal yang paling sering bikin angka salah: NULL dilewat sama semua fungsi kecuali COUNT(*), dan kondisi agregat wajib di HAVING bukan WHERE.

Coba jalanin query agregat per kota di data kerjaan kamu, terus bandingin COUNT(*) sama COUNT(DISTINCT id_pelanggan). Selisihnya sering bikin kaget — dan itu insight pertama kamu.

Buat ngerapiin dasar query-nya, mampir ke panduan SELECT SQL atau DISTINCT SQL.

Coba Langsung

Mau praktek langsung? Mulai latihan SQL gratis

Latihan interaktif, langsung di browser.

Buka NgulikSQL →
Bagikan:
Bima
Ditulis oleh

Bima

Founder & Data Professional

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

Artikel Terkait

7 SQL Client Gratis Terbaik buat Analis Data (2026)
Tutorial SQL
10 Juli 2026•9 menit baca

7 SQL Client Gratis Terbaik buat Analis Data (2026)

Nggak perlu bayar buat nulis query. Ini 7 SQL client gratis yang beneran dipakai analis, plus kelebihan dan kekurangannya masing-masing.

BimaBima
SQL Style Guide: Cara Nulis Query yang Enak Dibaca Tim
Tutorial SQL
7 Juli 2026•9 menit baca

SQL Style Guide: Cara Nulis Query yang Enak Dibaca Tim

Sepuluh aturan SQL style guide yang bikin query kamu kebaca sama tim — dan sama kamu sendiri 6 bulan lagi. Lengkap dengan contoh sebelum-sesudah.

BimaBima
Take-Home Test SQL Data Analyst: Contoh Soal + Cara Ngerjainnya
Tutorial SQL
4 Juli 2026•11 menit baca

Take-Home Test SQL Data Analyst: Contoh Soal + Cara Ngerjainnya

Contoh soal take-home test SQL yang beneran dipakai perusahaan, dikerjain step by step — dari baca soal, nulis query, sampai nyusun insight yang bikin recruiter nengok.

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
SupportPricingDatasetBlogAffiliates
LEGAL
Terms of servicesPrivacy policy
Ngulik Data
DatasetLeaderboardBlogStore