Total penjualan sebesar 1280000.00 terdengar mengesankan — sampai kita tahu bahwa angka itu berasal dari dua belas transaksi yang masing-masing kecil. Rata-rata adalah angka yang membuat total bisa dibandingkan: nilai transaksi tipikal, harga jual rata-rata, diskon rata-rata per pelanggan. Fungsi agregasi AVG menghitungnya dengan membagi jumlah nilai dengan banyaknya nilai. Pada chapter ini kita akan bedah perilaku AVG yang paling sering membingungkan pemula: format desimalnya yang lebih panjang dari kolom aslinya, dan kebiasaannya mengabaikan NULL — bukan memperlakukannya sebagai nol. Kita juga akan membuktikan bahwa AVG memang setara dengan SUM dibagi COUNT versi MySQL.

Menyiapkan Tabel Latihan #

Kita pakai tabel penjualan yang sama seperti dua chapter sebelumnya, ditambah satu kolom baru: diskon bertipe DECIMAL(7,2) yang boleh NULL. Hanya delapan dari dua belas transaksi yang mendapat diskon — empat baris bernilai NULL — sehingga efek pengabaian NULL bisa kita amati dengan jelas:

sql
DROP DATABASE IF EXISTS belajar_agregasi;
CREATE DATABASE belajar_agregasi;
USE belajar_agregasi;

Output yang Dihasilkan:

text
Query OK, 0 rows affected, 1 warning (0.00 sec)

Query OK, 1 row affected (0.00 sec)

Database changed
sql
CREATE TABLE penjualan (
  id INT AUTO_INCREMENT PRIMARY KEY,
  tanggal DATE NOT NULL,
  kota VARCHAR(50) NOT NULL,
  produk VARCHAR(50) NOT NULL,
  jumlah INT NOT NULL,
  harga DECIMAL(10,2) NOT NULL,
  diskon DECIMAL(7,2) NULL
);

INSERT INTO penjualan (tanggal, kota, produk, jumlah, harga, diskon) VALUES
  ('2026-01-05', 'Jakarta',    'Kopi Gayo',   2, 55000.00, 2000.00),
  ('2026-01-05', 'Bandung',    'Teh Melati',  3, 25000.00, 1000.00),
  ('2026-01-06', 'Jakarta',    'Teh Melati',  1, 25000.00, NULL),
  ('2026-01-07', 'Surabaya',   'Kopi Toraja', 5, 62000.00, 2000.00),
  ('2026-01-08', 'Bandung',    'Gula Aren',   4, 15000.00, 1000.00),
  ('2026-01-09', 'Jakarta',    'Gula Aren',   2, 15000.00, NULL),
  ('2026-01-10', 'Yogyakarta', 'Kopi Gayo',   3, 55000.00, 2000.00),
  ('2026-01-11', 'Surabaya',   'Teh Melati',  2, 25000.00, 1000.00),
  ('2026-01-12', 'Yogyakarta', 'Kopi Toraja', 1, 62000.00, NULL),
  ('2026-01-13', 'Jakarta',    'Kopi Toraja', 4, 62000.00, 2000.00),
  ('2026-01-14', 'Bandung',    'Kopi Gayo',   1, 55000.00, 1000.00),
  ('2026-01-15', 'Surabaya',   'Gula Aren',   6, 15000.00, NULL);

Output yang Dihasilkan:

text
Query OK, 0 rows affected (0.00 sec)

Query OK, 12 rows affected (0.00 sec)
Records: 12  Duplicates: 0  Warnings: 0

Total seluruh diskon adalah 12000.00 dari delapan transaksi berdiskon: empat transaksi berdiskon 2000.00 dan empat lainnya 1000.00. Angka-angka ini sengaja dibuat mudah dihitung manual, sehingga setiap hasil AVG pada chapter ini bisa kita verifikasi dengan kepala sendiri — kebiasaan yang sebaiknya dipertahankan saat belajar fungsi agregasi.

Menghitung Rata-rata Sederhana #

Bentuk dasarnya menyebutkan satu kolom angka:

sql
SELECT AVG(jumlah) AS rata_jumlah
FROM penjualan;

Output yang Dihasilkan:

text
+-------------+
| rata_jumlah |
+-------------+
|      2.8333 |
+-------------+
1 row in set (0.00 sec)

Hasilnya 2.8333 — total 34 unit dibagi dua belas baris. Perhatikan formatnya: kolom jumlah bertipe INT tanpa desimal, tetapi hasil AVG-nya tampil dengan empat angka desimal. Ini bukan bug melainkan aturan tipe: untuk argumen bilangan bulat, AVG menghasilkan DECIMAL dengan skala empat digit (nilai 34/12 = 2.83333... dibulatkan ke 2.8333). Bagaimana dengan kolom yang memang berdesimal? Mari kita uji:

sql
SELECT AVG(harga) AS rata_harga
FROM penjualan;

Output yang Dihasilkan:

text
+--------------+
| rata_harga   |
+--------------+
| 39250.000000 |
+--------------+
1 row in set (0.00 sec)

Hasilnya 39250.000000 — enam angka desimal, padahal kolom harga hanya punya dua. Aturannya konsisten: skala hasil AVG adalah skala kolom ditambah empat digit, sehingga DECIMAL(10,2) menghasilkan DECIMAL(...,6) dan INT (skala nol) menghasilkan empat digit. Nilai rata-rata sebenarnya tetap presisi di dalam hasil tersebut; hanya tampilannya yang membawa lebih banyak digit daripada yang kita biasakan lihat pada kolom uang.

NULL Diabaikan, Bukan Dihitung Nol #

Sekarang uji kolom diskon yang mengandung NULL pada empat baris:

sql
SELECT COUNT(*) AS semua_baris,
       COUNT(diskon) AS baris_berdiskon,
       SUM(diskon) AS total_diskon,
       AVG(diskon) AS rata_diskon
FROM penjualan;

Output yang Dihasilkan:

text
+-------------+-----------------+--------------+-------------+
| semua_baris | baris_berdiskon | total_diskon | rata_diskon |
+-------------+-----------------+--------------+-------------+
|          12 |               8 |     12000.00 | 1500.000000 |
+-------------+-----------------+--------------+-------------+
1 row in set (0.00 sec)

Empat kolom hasil menceritakan kisah yang lengkap: dua belas baris, delapan baris berdiskon, total 12000.00, dan rata-rata 1500.000000. Angka rata-rata tersebut berasal dari 12000.00 / 8, bukan 12000.00 / 12 — AVG mengabaikan baris yang kolomnya NULL sepenuhnya, sebagaimana SUM dan COUNT(kolom) melakukannya. Rata-rata yang dihitung adalah “rata-rata dari transaksi yang benar-benar memiliki diskon”.

Untuk membuktikannya, kita hitung dua versi rata-rata manual dengan SUM dan COUNT:

sql
SELECT SUM(diskon) / COUNT(diskon) AS rata_manual_non_null,
       SUM(diskon) / COUNT(*) AS rata_manual_semua_baris
FROM penjualan;

Output yang Dihasilkan:

text
+----------------------+-------------------------+
| rata_manual_non_null | rata_manual_semua_baris |
+----------------------+-------------------------+
|          1500.000000 |             1000.000000 |
+----------------------+-------------------------+
1 row in set (0.00 sec)

Versi pertama menghasilkan 1500.000000 — persis sama dengan AVG(diskon) — sedangkan versi kedua menghasilkan 1000.000000. Pembuktian ini penting karena menjelaskan apa yang sebenarnya dijanjikan AVG: fungsi ini adalah singkatan dari SUM(kolom) / COUNT(kolom), keduanya mengabaikan NULL. Bila kebutuhan bisnis kita justru “rata-rata diskon jika setiap transaksi tanpa diskon dianggap nol”, angka yang benar adalah 1000.000000, dan cara mendapatkannya adalah AVG(IFNULL(diskon, 0)):

sql
SELECT AVG(IFNULL(diskon, 0)) AS rata_diskon_nol
FROM penjualan;

Output yang Dihasilkan:

text
+-----------------+
| rata_diskon_nol |
+-----------------+
|     1000.000000 |
+-----------------+
1 row in set (0.00 sec)

Fungsi IFNULL(diskon, 0) mengganti setiap NULL menjadi 0 sebelum nilai masuk ke AVG, sehingga pembaginya kembali menjadi dua belas baris. Hasilnya 1000.000000 — sama dengan versi SUM / COUNT(*). Dua angka yang berbeda ini sama-sama “benar”; yang menentukan pilihan adalah makna yang kita inginkan.

Merapikan Tampilan dengan ROUND #

Untuk laporan yang dibaca manusia, enam digit desimal lebih sering mengganggu daripada membantu. Fungsi ROUND membulatkan hasil ke jumlah desimal yang kita tentukan:

sql
SELECT ROUND(AVG(harga), 2) AS rata_harga_2desimal,
       ROUND(AVG(diskon), 0) AS rata_diskon_bulat
FROM penjualan;

Output yang Dihasilkan:

text
+---------------------+-------------------+
| rata_harga_2desimal | rata_diskon_bulat |
+---------------------+-------------------+
|            39250.00 |              1500 |
+---------------------+-------------------+
1 row in set (0.00 sec)

Rata-rata harga tampil sebagai 39250.00 dan rata-rata diskon menjadi 1500 tanpa desimal. Perhatikan urutan kerjanya: AVG menghitung dengan presisi penuh terlebih dahulu, baru ROUND membulatkan hasil akhirnya — menulis AVG(ROUND(harga, 2)) pada kolom yang memang sudah dua desimal tidak mengubah apa pun. ROUND di sini murni urusan tampilan hasil query; nilai yang tersimpan di tabel tidak pernah tersentuh.

Membersihkan Database Latihan #

Latihan rata-rata selesai; database latihan kita hapuskan kembali:

sql
DROP DATABASE belajar_agregasi;

Output yang Dihasilkan:

text
Query OK, 1 row affected (0.00 sec)

Referensi #

Kini kita menguasai tiga agregat penghitung angka: COUNT untuk jumlah, SUM untuk total, dan AVG untuk rata-rata — termasuk jebakan NULL dan format desimalnya. Satu jenis pertanyaan belum terjawab: bukan “berapa banyak” atau “berapa rata-ratanya”, melainkan “yang paling”. Berapa transaksi terbesar, harga termahal, tanggal penjualan pertama? Chapter berikutnya membahas MIN dan MAX, dua fungsi yang juga punya kebiasaan khas saat bertemu teks dan tanggal.