Running Max dan Min dengan Window Function SQL
Blog/Tutorial SQL/Running Max dan Min dengan Window Function SQL

Running Max dan Min dengan Window Function SQL

BimaBima
·26 Desember 2026·11 menit baca

Penulis

Bima

Bima

Founder & Data Professional

Bagikan

TL;DR

Running max dan running min di SQL dihitung pakai window function MAX() OVER (ORDER BY ...) dan MIN() OVER (ORDER BY ...). Fungsi ini ngasih nilai tertinggi atau terendah dari baris pertama sampai baris saat ini, jadi kamu bisa lacak rekor berjalan tanpa self-join. Tambahin PARTITION BY buat menghitung rekor terpisah per grup seperti per cabang atau per produk.

Running max dan running min di SQL dihitung pakai window function MAX() OVER (ORDER BY ...) dan MIN() OVER (ORDER BY ...), yang ngasih nilai tertinggi atau terendah dari baris pertama sampai baris saat ini.

Ini berguna banget buat lacak rekor. Rekor omzet harian tertinggi sepanjang tahun, harga saham terendah sampai hari ini, atau suhu maksimum yang pernah tercatat. Tanpa window function, kamu bakal ribet pakai subquery atau self-join.

Di tutorial ini kamu bakal belajar sintaks running max dan min dari dasar, cara pakai frame clause, dan cara reset per grup pakai PARTITION BY. Semua pakai contoh dataset toko Indonesia.

Apa itu running max dan running min di SQL?

Running max adalah nilai tertinggi yang tercatat dari baris pertama sampai baris saat ini. Running min kebalikannya, nilai terendah sampai titik itu. Beda sama MAX biasa yang ngasih satu angka buat seluruh data, running max ngasih nilai berjalan di tiap baris sambil tetap nampilin semua baris asli.

Contoh gampangnya. Kalau omzet harian toko naik turun, running max nunjukin rekor tertinggi yang pernah dicapai sampai tiap tanggal. Begitu ada hari yang lebih tinggi dari rekor lama, running max-nya naik. Kalau gak, dia bertahan.

Ini termasuk keluarga window function, kelompok fungsi SQL yang ngitung sesuatu di sekumpulan baris tanpa nge-grup datanya jadi satu.

Gimana sintaks window function buat running max?

Sintaks dasarnya taruh MAX(kolom) lalu tambahin OVER (ORDER BY kolom_urutan). Bagian ORDER BY di dalam OVER yang bikin MAX-nya jadi berjalan, karena dia nentuin urutan baris dihitung dari mana ke mana.

SELECT
  tgl,
  omzet,
  MAX(omzet) OVER (ORDER BY tgl) AS rekor_tertinggi,
  MIN(omzet) OVER (ORDER BY tgl) AS rekor_terendah
FROM penjualan_harian
ORDER BY tgl;

Hasilnya tiap baris nampilin omzet hari itu, plus rekor tertinggi dan terendah sampai tanggal tersebut. Perhatiin jumlah barisnya gak berkurang, beda sama kalau kamu pakai GROUP BY.

tglomzetrekor_tertinggirekor_terendah
01 Des2.400.0002.400.0002.400.000
02 Des1.750.0002.400.0001.750.000
03 Des3.100.0003.100.0001.750.000
04 Des1.200.0003.100.0001.200.000

Lihat kolom rekor_tertinggi di baris 03 Des naik jadi 3,1 juta karena hari itu pecah rekor. Di 04 Des dia bertahan walau omzetnya turun.

Gimana cara kerja frame clause?

Waktu kamu pakai ORDER BY di dalam OVER, SQL diam-diam nambahin frame default: ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW. Artinya window-nya ngitung dari baris pertama sampai baris saat ini. Inilah yang bikin MAX jadi running max.

MAX(omzet) OVER (
  ORDER BY tgl
  ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS rekor_tertinggi

Query di atas hasilnya sama persis dengan versi tanpa frame, karena itu memang default-nya. Tapi nulis eksplisit bikin maksudmu jelas.

Kalau kamu mau moving max, misalnya nilai tertinggi dari 3 hari terakhir aja, tinggal ubah frame-nya:

MAX(omzet) OVER (
  ORDER BY tgl
  ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
) AS max_3_hari

Sekarang window-nya cuma nengok 3 baris terakhir, bukan dari awal. Frame clause ini yang ngasih window function keluwesan besar.

Contoh kasus: melacak rekor omzet toko_berkah

Ambil dataset toko_berkah dengan 90 hari data omzet harian. Aku mau tau kapan aja toko ini pecah rekor omzet, dan berapa rekornya di tiap titik. Query running max langsung ngejawab.

SELECT
  tgl,
  omzet,
  MAX(omzet) OVER (ORDER BY tgl) AS rekor_berjalan,
  CASE
    WHEN omzet = MAX(omzet) OVER (ORDER BY tgl)
    THEN 'REKOR BARU'
    ELSE ''
  END AS status
FROM penjualan_harian
ORDER BY tgl;

Kolom CASE nandain hari yang pecah rekor. Dari 90 hari data, ternyata cuma 7 hari yang pecah rekor omzet, dan 4 di antaranya jatuh di minggu menjelang Lebaran. Insight kayak gini susah dapet tanpa running max.

Angka ini juga ngasih tau kapan momentum penjualan lagi kuat. Kalau rekor berjalan mandek berminggu-minggu, itu sinyal penjualan lagi stagnan.

Running max per grup dengan PARTITION BY

Kalau toko_berkah punya beberapa cabang, kamu pasti mau rekor terpisah per cabang. Tambahin PARTITION BY cabang di dalam OVER. Hitungan running max bakal reset tiap ganti cabang.

SELECT
  cabang,
  tgl,
  omzet,
  MAX(omzet) OVER (
    PARTITION BY cabang
    ORDER BY tgl
  ) AS rekor_cabang
FROM penjualan_harian
ORDER BY cabang, tgl;

Sekarang tiap cabang punya rekor berjalannya sendiri. Cabang Bekasi gak nyampur sama cabang Depok. Ini cara paling bersih buat bandingin performa antar toko tanpa nulis query terpisah buat masing-masing.

Buat teknik window function lain yang mirip, baca cara hitung running total di SQL.

Kesalahan umum pakai running max dan min

Window function powerful tapi ada beberapa jebakan yang sering bikin hasil salah.

  • Lupa ORDER BY di dalam OVER. Tanpa ORDER BY, MAX OVER ngasih nilai tertinggi seluruh tabel di tiap baris, bukan rekor berjalan.
  • Nyampur GROUP BY dan window function tanpa paham bedanya. GROUP BY nyusutin baris, window function nggak. Pilih sesuai kebutuhan.
  • Lupa PARTITION BY pas butuh per grup. Tanpa PARTITION BY, rekornya kecampur antar cabang atau produk.
  • Pakai di MySQL versi lama. Window function baru ada di MySQL 8. Versi 5.7 ke bawah bakal error.

Kalau kamu masih baru di window function, mulai dari pengenalan window function SQL dulu biar konsepnya nyantol.

FAQ

Pertanyaan yang sering muncul soal running max dan min di SQL.

Penutup

Running max dan running min bikin kamu bisa lacak rekor tertinggi dan terendah berjalan cuma dengan satu window function, tanpa self-join yang ribet. Kuncinya ORDER BY di dalam OVER, plus PARTITION BY kalau butuh per grup.

Ingat frame default-nya dari baris pertama sampai baris saat ini. Ubah frame-nya kalau kamu mau moving max yang cuma nengok beberapa baris terakhir.

Mau latihan window function pakai data nyata? Editor SQL interaktif ada di NgulikSQL, dan lanjut baca panduan running total buat teknik sejenis. Referensi resmi sintaksnya ada di dokumentasi window function PostgreSQL.

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

Fungsi NTH_VALUE di SQL untuk Ambil Nilai ke-N (2026)
Tutorial SQL
29 Desember 2026•9 menit baca

Fungsi NTH_VALUE di SQL untuk Ambil Nilai ke-N (2026)

NTH_VALUE ngambil nilai baris ke-N dalam window, tapi frame default-nya sering bikin hasil NULL. Ini sintaksnya, cara benerin frame, plus contoh transaksi toko.

BimaBima
Analisa Afinitas Produk (Cross-Sell) dengan SQL
Tutorial SQL
23 Desember 2026•12 menit baca

Analisa Afinitas Produk (Cross-Sell) dengan SQL

Produk apa yang sering dibeli bareng? Analisa afinitas produk pakai SQL self JOIN jawab itu. Ini cara hitung support, confidence, dan lift buat strategi cross-sell.

BimaBima
First Touch vs Last Touch Attribution di SQL
Tutorial SQL
20 Desember 2026•12 menit baca

First Touch vs Last Touch Attribution di SQL

Channel mana yang dapat kredit konversi, yang pertama atau terakhir? Ini cara hitung first touch dan last touch attribution di SQL pakai window function.

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.

© 2026 Ngulik Data. Semua hak dilindungi.

TAUTAN
BantuanHargaDatasetBlogAfiliasi
LEGAL
Syarat & KetentuanKebijakan Privasi
Ngulik Data
DatasetLeaderboardBlogStore