MIN dan MAX SQL: Cari Nilai Ekstrem plus Trik Baris Terkait
TL;DR
MAX di SQL mengembalikan nilai terbesar dari sebuah kolom dan MIN mengembalikan yang terkecil, contohnya MAX(total) dan MIN(tanggal). Dua-duanya cuma mengembalikan angkanya, bukan baris tempat angka itu berada. Buat ambil baris lengkapnya, pakai ORDER BY ... LIMIT 1 untuk satu baris, atau window function ROW_NUMBER kalau kamu butuh baris teratas per grup.
MAX di SQL ngambil nilai terbesar dari sebuah kolom. MIN ngambil yang terkecil.
SELECT MAX(total) AS transaksi_terbesar,
MIN(total) AS transaksi_terkecil
FROM penjualan;
Dua baris, selesai. Masalahnya muncul di pertanyaan lanjutan yang hampir selalu ditanya bos kamu: "transaksi 120.000 itu punya siapa?"
MAX nggak bisa jawab. Dia ngeluarin angka, bukan baris.
Apa itu MIN dan MAX di SQL?
MIN dan MAX adalah fungsi agregat yang ngambil satu nilai ekstrem dari banyak baris. MAX ngasih nilai terbesar di kolom yang kamu sebut, MIN ngasih yang terkecil. Dua-duanya ngelewatin baris NULL, dan dua-duanya jalan di kolom angka, tanggal, maupun teks.
Di kolom tanggal, MIN artinya paling awal. Di kolom teks, urutannya alfabet.
Fungsi agregat lain yang sering dipakai bareng ada di panduan fungsi agregat SQL.
Gimana cara pakai MIN dan MAX?
Pakai tabel penjualan dari dataset toko_berkah, 10 transaksi Januari 2026.
| id | tanggal | kota | kategori | total | ongkir |
|---|---|---|---|---|---|
| 1 | 2026-01-03 | Bandung | Minuman | 30.000 | NULL |
| 2 | 2026-01-05 | Bandung | Makanan | 45.000 | 10.000 |
| 3 | 2026-01-07 | Surabaya | Minuman | 45.000 | 12.000 |
| 4 | 2026-01-09 | Surabaya | Sembako | 120.000 | NULL |
| 5 | 2026-01-12 | Medan | Makanan | 90.000 | 15.000 |
| 6 | 2026-01-15 | Bandung | Sembako | 120.000 | 10.000 |
| 7 | 2026-01-18 | Medan | Minuman | 60.000 | NULL |
| 8 | 2026-01-21 | Surabaya | Makanan | 45.000 | 12.000 |
| 9 | 2026-01-25 | Bandung | Minuman | 30.000 | 10.000 |
| 10 | 2026-01-28 | Medan | Sembako | 120.000 | 15.000 |
SELECT MAX(total) AS transaksi_terbesar,
MIN(total) AS transaksi_terkecil,
MIN(tanggal) AS transaksi_pertama,
MAX(tanggal) AS transaksi_terakhir
FROM penjualan;
-- 120000 | 30000 | 2026-01-03 | 2026-01-28
MIN dan MAX di kolom tanggal ini sering aku pakai buat cek rentang data. Sebelum bikin laporan bulanan, aku selalu jalanin dulu — mastiin datanya beneran nyampe akhir bulan.
Apakah MIN dan MAX ngitung NULL?
Nggak. Dua-duanya ngelewatin NULL diam-diam.
SELECT MIN(ongkir) AS ongkir_termurah,
MAX(ongkir) AS ongkir_termahal
FROM penjualan;
-- 10000 | 15000
Tiga baris ongkirnya NULL, dan tiga-tiganya dilewati. Hasilnya tetap angka, bukan NULL.
Ini beda dari intuisi banyak orang: mereka nyangka nilai "paling kecil" harusnya kosong. Kalau NULL di kolom kamu artinya nol, bungkus pakai COALESCE(ongkir, 0) dulu. Perilaku NULL lengkapnya ada di glosarium NULL.
Kenapa MAX nggak bisa digabung sama kolom biasa?
Query ini kelihatan masuk akal. Tapi salah.
-- SALAH
SELECT kota, kategori, MAX(total)
FROM penjualan;
MAX memampatkan 10 baris jadi 1 angka. Kolom kota punya 10 nilai berbeda. Database bingung mana yang mau ditampilin.
PostgreSQL langsung nolak dengan pesan error. MySQL versi lama malah ngizinin dan ngasih nilai acak — dan ini lebih bahaya, soalnya hasilnya kelihatan bener padahal ngawur.
Gimana cara ambil baris lengkap dari nilai tertinggi?
Ada tiga cara. Pilih sesuai kebutuhan.
1. ORDER BY + LIMIT (paling gampang)
SELECT *
FROM penjualan
ORDER BY total DESC, id_transaksi ASC
LIMIT 1;
-- id 4 | 2026-01-09 | Surabaya | Sembako | 120000
Urutin dari besar ke kecil, ambil satu. Aku selalu nambahin id_transaksi di ORDER BY sebagai pemecah seri — tanpa itu, hasilnya bisa beda tiap kali query dijalanin.
Di SQL Server, ganti LIMIT jadi SELECT TOP 1.
2. Subquery (kalau butuh semua yang seri)
SELECT *
FROM penjualan
WHERE total = (SELECT MAX(total) FROM penjualan);
Di dataset ini, hasilnya 3 baris: id 4, 6, dan 10. Tiga-tiganya 120.000.
LIMIT 1 cuma ngasih satu. Subquery ngasih semuanya. Beda hasil, beda pertanyaan.
3. Window function (buat top per grup)
SELECT kota, kategori, tanggal, total
FROM (
SELECT p.*,
ROW_NUMBER() OVER (PARTITION BY kota ORDER BY total DESC, id_transaksi) AS urutan
FROM penjualan p
) t
WHERE urutan = 1;
PARTITION BY bikin penomoran ulang di tiap kota. Baris nomor 1 di tiap kota = transaksi terbesarnya. Sekali query, dapat pemenang semua kota.
Contoh kasus: MIN yang ngungkap apa yang MAX sembunyiin
SELECT kota,
MAX(total) AS terbesar,
MIN(total) AS terkecil
FROM penjualan
GROUP BY kota
ORDER BY kota;
| kota | terbesar | terkecil |
|---|---|---|
| Bandung | 120.000 | 30.000 |
| Medan | 120.000 | 60.000 |
| Surabaya | 120.000 | 45.000 |
MAX ketiga kota di toko_berkah identik: 120.000. Tapi MIN-nya beda dua kali lipat — Bandung 30.000, Medan 60.000. Kalau kamu cuma laporin MAX, tiga kota ini kelihatan sama padahal perilaku belanjanya beda jauh.
Pelanggan Bandung banyak yang beli eceran kecil. Pelanggan Medan nggak pernah belanja di bawah 60.000. Insight ini nggak muncul dari MAX, dan nggak muncul dari SUM atau AVG juga.
Kesalahan umum waktu pakai MIN dan MAX
- Nyangka MAX ngasih barisnya. Nggak. Dia cuma ngasih angka. Pakai ORDER BY LIMIT atau window function.
- Lupa pemecah seri di ORDER BY. Kalau tiga baris nilainya sama, LIMIT 1 bisa ngasih baris berbeda tiap dijalanin.
- Pakai WHERE buat nyaring hasil MAX. WHERE jalan sebelum agregasi. Pakai HAVING.
- MIN di kolom teks nggak sesuai harapan. Urutannya ngikutin collation. Di beberapa database, huruf besar diurutkan sebelum huruf kecil.
- MAX di kolom tanggal bertipe teks. Kalau tanggalnya disimpan sebagai VARCHAR dengan format DD/MM/YYYY, MAX ngasih hasil ngawur. Simpan sebagai DATE.
Perilaku lengkapnya bisa kamu cek di dokumentasi PostgreSQL untuk aggregate functions.
FAQ
Gimana cara ambil baris dengan nilai tertinggi di SQL?
Paling gampang: SELECT * FROM penjualan ORDER BY total DESC LIMIT 1. Kalau butuh baris tertinggi per grup, pakai ROW_NUMBER() OVER (PARTITION BY kota ORDER BY total DESC) lalu saring yang nomornya 1.
Apakah MIN dan MAX mengabaikan NULL?
Iya. Mereka ngelewatin baris NULL dan nggak akan pernah ngasih NULL kecuali seluruh kolomnya NULL. Di toko_berkah, MIN(ongkir) ngasih 10.000 walaupun ada 3 baris NULL.
MIN dan MAX bisa dipakai di kolom teks?
Bisa. Urutannya ngikutin collation database. MIN(kota) di data ini ngasih Bandung, soalnya B paling awal secara alfabet.
Apa bedanya MAX sama ORDER BY DESC LIMIT 1?
MAX ngasih angka, ORDER BY LIMIT ngasih baris lengkapnya. Kalau kamu cuma butuh angkanya, MAX lebih cepat — database nggak perlu ngurutin seluruh tabel.
Rangkuman
- MAX dan MIN ngambil nilai ekstrem, ngelewatin NULL, dan jalan di angka, tanggal, maupun teks.
- Butuh baris lengkapnya? ORDER BY DESC LIMIT 1 buat satu baris, ROW_NUMBER buat top per grup.
- Kalau MAX antar grup kelihatan seragam, cek MIN-nya. Di toko_berkah, MIN ngungkap selisih 2x antar kota.
Query di artikel ini udah dites dan siap copy-paste. Latihan langsung di halaman fungsi MAX — editornya jalan di browser.
Lanjut baca: Operator LIKE SQL buat nyari teks pakai wildcard.
Mau praktek langsung? Mulai latihan SQL gratis
Latihan interaktif, langsung di browser.
Artikel Terkait
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.
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.
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.