Pertanyaan dari tim manajemen toko online jarang menyangkut satu baris: “berapa total pendapatan bulan ini?”, “berapa rata-rata harga produk?”, “produk termurah dan termahal berapa?”. Semua jawaban tersebut berupa satu angka yang dirangkum dari banyak baris — pekerjaan fungsi agregasi. Chapter ini membahas lima fungsi agregasi inti SQL pada tabel toko online dari chapter Pengenalan SQL, dengan perhatian khusus pada NULL karena nilai kosong mengubah hasil perhitungan.

Lima Fungsi Agregasi Inti #

FungsiPeranContoh pada tabel toko
COUNTmenghitung jumlah baris atau nilaijumlah pelanggan terdaftar
SUMmenjumlahkan nilai numeriktotal pendapatan dari subtotal
AVGmenghitung rata-rata nilairata-rata harga produk
MINmencari nilai terkecilharga produk termurah
MAXmencari nilai terbesarharga produk termahal

Satu query boleh memuat beberapa fungsi agregasi sekaligus; setiap fungsi meringkas seluruh baris tabel menjadi satu nilai pada satu baris hasil:

sql
SELECT COUNT(*) AS jumlah_produk,
       MIN(harga) AS harga_terendah,
       MAX(harga) AS harga_tertinggi,
       AVG(harga) AS harga_rata_rata
FROM produk

Output yang Dihasilkan:

text
(6, 250000, 12500000, 3046666.6666666665)

Mari kita telaah query di atas: klausa FROM produk menentukan sumber data, COUNT(*) menghitung enam baris produk, MIN dan MAX memindai kolom harga untuk batas terendah dan tertinggi, sedangkan AVG membagi jumlah seluruh harga (18.280.000) dengan jumlah produk (6) menjadi 3.046.666,67. Hasil AVG bertipe bilangan desimal meskipun kolom aslinya bilangan bulat. Alias seperti AS harga_rata_rata hanya memberi nama pada kolom hasil dan tidak mengubah perhitungan.

COUNT(*) vs COUNT(kolom) #

COUNT punya dua bentuk yang sering tertukar. COUNT(*) menghitung jumlah baris tanpa peduli isi, sedangkan COUNT(kolom) menghitung jumlah nilai non-NULL pada kolom tersebut:

sql
SELECT COUNT(*) AS total_baris, COUNT(kota) AS kota_terisi
FROM pelanggan

Output yang Dihasilkan:

text
(6, 5)

Tabel pelanggan memiliki enam baris, tetapi hanya lima nilai kota karena Andi Wijaya belum mengisi kota. Perbedaan yang sama terlihat pada tabel transaksi:

sql
SELECT COUNT(*) AS total_baris, COUNT(subtotal) AS subtotal_terisi
FROM detail_pesanan

Output yang Dihasilkan:

text
(11, 10)

Sebelas baris detail pesanan berisi sepuluh subtotal karena pesanan 5 yang dibatalkan tidak pernah dihitung subtotalnya. Gunakan COUNT(*) untuk menghitung kejadian dan COUNT(kolom) untuk menghitung kelengkapan data — salah memilih bentuk membuat laporan jumlah transaksi bisa meleset satu angka. Bentuk ketiga, COUNT(DISTINCT kategori), menghitung nilai berbeda saja:

sql
SELECT COUNT(DISTINCT kategori) AS jumlah_kategori FROM produk

Output yang Dihasilkan:

text
(2,)

SUM dan AVG Terhadap NULL #

Fungsi SUM, AVG, MIN, dan MAX mengabaikan NULL sepenuhnya — nilai kosong tidak dianggap nol, melainkan dikeluarkan dari perhitungan:

sql
SELECT SUM(subtotal) AS total_pendapatan
FROM detail_pesanan

Output yang Dihasilkan:

text
(21430000,)

Perilaku tersebut terlihat jelas saat beberapa fungsi digabungkan:

sql
SELECT SUM(subtotal) AS total,
       AVG(subtotal) AS rata_rata,
       MIN(subtotal) AS terkecil,
       MAX(subtotal) AS terbesar
FROM detail_pesanan

Output yang Dihasilkan:

text
(21430000, 2143000.0, 250000, 12500000)

AVG membagi jumlah nilai non-NULL dengan banyaknya nilai non-NULL: 21.430.000 dibagi 10 — bukan dibagi 11 baris. MIN dan MAX juga melewati NULL; nilai terkecil tetap 250000, bukan NULL. Ketika seluruh nilai pada kelompok kosong, SUM mengembalikan NULL, bukan nol — perilaku yang memengaruhi laporan keuangan.

Aturan Dasar Agregasi #

Query agregasi tanpa GROUP BY selalu mengembalikan tepat satu baris, bahkan ketika tabelnya kosong — COUNT(*) menghasilkan 0, sementara SUM, AVG, MIN, dan MAX menghasilkan NULL. Konsekuensi penting berikutnya: kolom biasa tidak boleh dicampur dengan fungsi agregasi dalam satu daftar SELECT karena tidak jelas nilai kolom mana yang harus ditampilkan pada satu baris rangkuman. PostgreSQL menolak query seperti SELECT nama, MAX(harga) FROM produk dengan pesan galat; SQLite menerima query tersebut dan menampilkan nilai dari salah satu baris — perilaku khusus SQLite yang tidak portabel. Bentuk yang benar untuk “produk mana yang paling mahal” adalah pengurutan dan pembatasan dari chapter Sorting dan Limiting, atau pengelompokan yang dibahas berikutnya. Daftar lengkap fungsi agregasi tersedia di dokumentasi SQLite dan PostgreSQL .

Satu angka untuk seluruh tabel sering terlalu kasar: total pendapatan per kota dan rata-rata harga per kategori jauh lebih informatif. Pemecahan tabel menjadi kelompok-kelompok adalah tugas chapter GROUP BY dan HAVING.