Running Total SQL: Hitung Akumulasi Penjualan per Hari
Blog/Tutorial SQL/Running Total SQL: Hitung Akumulasi Penjualan per Hari

Running Total SQL: Hitung Akumulasi Penjualan per Hari

BimaBima
·21 April 2026·12 menit baca

Penulis

Bima

Bima

Founder & Data Professional

Bagikan

TL;DR

Running total SQL adalah akumulasi berjalan — total sampai baris ini, termasuk semua baris sebelumnya. Cara nulisnya pakai window function: SUM(omzet) OVER (ORDER BY tanggal). Klausa ORDER BY di dalam OVER yang nentuin urutan akumulasinya, dan kamu bisa pisahin per grup pakai PARTITION BY, misalnya per kota. Jebakan yang paling sering: tanggal yang nggak ada transaksinya bakal ilang dari hasil, jadi grafik akumulasinya keliatan bolong.

Running total SQL adalah akumulasi berjalan — total sampai baris ini, termasuk semua baris sebelumnya.

Omzet 1 April Rp 12 juta. 2 April Rp 15 juta. Running total di tanggal 2: Rp 27 juta.

Query-nya satu baris tambahan doang:

SUM(total) OVER (ORDER BY tanggal) AS running_total

Yang bikin banyak orang mundur bukan sintaksnya. Tapi bagian OVER yang kelihatan asing.

Apa itu running total di SQL?

Running total adalah kolom hasil hitungan yang nunjukin jumlah kumulatif dari baris pertama sampai baris yang lagi dibaca. Di SQL, ini dikerjain sama window function — fungsi yang ngitung agregat tapi tetap nyimpen semua baris aslinya, beda dari GROUP BY yang nge-collapse baris jadi satu.

Bedanya di sini:

FungsiInput 30 barisOutput
SUM(total) + GROUP BY30 transaksi1 baris total
SUM(total) OVER (...)30 transaksi30 baris + kolom akumulasi

Itu yang bikin window function berguna buat running total. Kamu masih lihat detail hariannya, plus akumulasinya di sebelah.

Gimana cara nulis running total SQL?

Sintaks dasarnya:

SELECT
    tanggal,
    total,
    SUM(total) OVER (ORDER BY tanggal) AS running_total
FROM penjualan
ORDER BY tanggal;

Tiga bagian yang perlu kamu paham:

  1. SUM(total) — apa yang mau diakumulasi.
  2. OVER — nandain ini window function, bukan agregasi biasa.
  3. ORDER BY tanggal di dalam kurung — urutan akumulasinya. Ini yang paling penting.

ORDER BY di dalam OVER beda sama ORDER BY di akhir query. Yang di dalam nentuin urutan penjumlahan. Yang di luar nentuin urutan tampilan. Sering kebetulan sama, tapi konsepnya beda.

Running total per hari, bukan per transaksi

Query di atas ngakumulasi per transaksi. Kalau ada 400 transaksi di 1 April, kamu dapat 400 baris.

Yang kamu mau biasanya per hari. Berarti kamu perlu GROUP BY dulu, baru akumulasi:

SELECT
    tanggal,
    SUM(total) AS omzet_harian,
    SUM(SUM(total)) OVER (ORDER BY tanggal) AS running_total
FROM penjualan
WHERE tanggal BETWEEN '2026-04-01' AND '2026-04-30'
GROUP BY tanggal
ORDER BY tanggal;

Iya, ada SUM(SUM(total)). Ini bukan typo.

SUM yang di dalam ngerjain GROUP BY — nghasilin omzet harian. SUM yang di luar (yang pakai OVER) ngakumulasi hasil itu.

SQL ngeksekusi GROUP BY dulu, baru window function. Makanya window function bisa "lihat" hasil agregasi.

Kalau kamu belum kenal GROUP BY, itu yang harus kamu kuasain duluan.

Contoh kasus: akumulasi omzet toko_berkah April 2026

Dataset toko_berkah — transaksi ritel UMKM dari 6 kota. Aku jalanin query di atas buat 10 hari pertama April:

TanggalOmzet HarianRunning Total
2026-04-01Rp 12.400.000Rp 12.400.000
2026-04-02Rp 14.800.000Rp 27.200.000
2026-04-03Rp 18.100.000Rp 45.300.000
2026-04-04Rp 24.600.000Rp 69.900.000
2026-04-05Rp 26.200.000Rp 96.100.000
2026-04-06Rp 11.900.000Rp 108.000.000
2026-04-07Rp 12.700.000Rp 120.700.000
2026-04-08Rp 13.100.000Rp 133.800.000
2026-04-09Rp 15.400.000Rp 149.200.000
2026-04-10Rp 22.900.000Rp 172.100.000

Ada pola yang cuma keliatan dari kolom akumulasi.

Tanggal 4 dan 5 (Sabtu-Minggu) nyumbang Rp 50,8 juta — 29% dari total 10 hari, cuma dari 2 hari. Weekday rata-rata Rp 13,4 juta per hari. Weekend Rp 25,4 juta.

Hampir 2x lipat.

Angka itu langsung ngubah keputusan: stok dikirim Jumat sore, bukan Senin pagi.

Running total per kota pakai PARTITION BY

Kalau kamu mau akumulasinya reset tiap ganti kota, tambahin PARTITION BY:

SELECT
    kota,
    tanggal,
    SUM(total) AS omzet_harian,
    SUM(SUM(total)) OVER (
        PARTITION BY kota
        ORDER BY tanggal
    ) AS running_total_kota
FROM penjualan
WHERE tanggal BETWEEN '2026-04-01' AND '2026-04-30'
GROUP BY kota, tanggal
ORDER BY kota, tanggal;

PARTITION BY kota mecah data jadi grup per kota. Akumulasinya jalan sendiri-sendiri di tiap grup, dan balik ke nol tiap ganti kota.

Ini yang paling sering dipakai buat bandingin kecepatan pertumbuhan antar wilayah dalam satu query.

Frame: ROWS BETWEEN

Ada bagian opsional yang jarang dipakai tapi penting waktu kepakai: frame.

SUM(total) OVER (
    ORDER BY tanggal
    ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS running_total

Ini nentuin baris mana aja yang ikut dijumlahin. UNBOUNDED PRECEDING artinya dari baris paling awal, CURRENT ROW artinya sampai baris ini.

Kalau kamu nggak nulis frame-nya, SQL pakai default ini juga. Jadi buat running total biasa, kamu nggak perlu nulisnya.

Tapi frame jadi berguna kalau kamu mau moving average 7 hari:

AVG(SUM(total)) OVER (
    ORDER BY tanggal
    ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
) AS rata_rata_7_hari

Ini yang ngeratain fluktuasi weekend-weekday tadi.

Kesalahan umum bikin running total

1. Tanggal bolong

Ini yang paling sering bikin grafik salah. Kalau tanggal 14 April nggak ada transaksi sama sekali, baris itu nggak muncul di hasil query.

SQL cuma balikin baris yang ada di tabel. Nggak ada transaksi = nggak ada baris.

Solusinya: bikin tabel kalender berisi semua tanggal, terus LEFT JOIN penjualan ke situ.

SELECT
    k.tanggal,
    COALESCE(SUM(p.total), 0) AS omzet_harian,
    SUM(COALESCE(SUM(p.total), 0)) OVER (ORDER BY k.tanggal) AS running_total
FROM kalender k
LEFT JOIN penjualan p ON p.tanggal = k.tanggal
WHERE k.tanggal BETWEEN '2026-04-01' AND '2026-04-30'
GROUP BY k.tanggal
ORDER BY k.tanggal;

COALESCE ngubah NULL jadi 0, jadi akumulasinya tetap jalan mulus. Cara kerja COALESCE aku bahas terpisah.

2. Lupa ORDER BY di dalam OVER

Kalau kamu nulis SUM(total) OVER () tanpa ORDER BY, hasilnya bukan running total — tapi grand total yang sama di semua baris. Nggak error, tapi salah.

3. ORDER BY pakai kolom yang nggak unik

Kalau ada 2 baris dengan tanggal sama dan kamu ORDER BY tanggal doang, urutan di antara keduanya nggak dijamin. Buat running total per hari ini nggak masalah, tapi buat running total per transaksi, tambahin tiebreaker: ORDER BY tanggal, order_id.

4. Pakai MySQL 5.7

Window function baru ada di MySQL 8.0. Di 5.7, query kamu bakal error syntax. Cek versinya pakai SELECT VERSION();.

5. WHERE yang motong data yang kamu butuh

Kalau kamu mau running total dari awal tahun tapi nulis WHERE tanggal >= '2026-04-01', akumulasinya mulai dari nol di April. Kalau maunya lanjutan dari Januari, jangan filter di WHERE — filter hasilnya belakangan pakai subquery.

Kompatibilitas antar database

DatabaseDukungan window function
PostgreSQLSejak 8.4 (2009)
MySQLSejak 8.0 (2018)
SQL ServerSejak 2012
BigQuerySejak awal
SQLiteSejak 3.25 (2018)

Sintaksnya nyaris identik di semuanya. Referensi lengkapnya ada di dokumentasi resmi PostgreSQL soal window function.

FAQ

Apa bedanya SUM biasa sama SUM OVER?

SUM biasa nge-collapse banyak baris jadi satu angka. Kamu punya 30 baris transaksi, hasilnya 1 baris total. SUM OVER tetap nyimpen semua baris, tapi nambahin satu kolom hasil hitungan di tiap baris. Jadi kamu masih lihat detail per hari, plus akumulasinya di sebelahnya. Itu yang bikin window function cocok buat running total.

Kenapa running total-ku loncat di beberapa tanggal?

Karena tanggal yang nggak ada transaksinya nggak muncul di hasil query. SQL cuma balikin baris yang ada di tabel. Kalau tanggal 14 April nggak ada penjualan sama sekali, dia hilang dan grafik kamu jadi bolong. Solusinya: bikin tabel kalender berisi semua tanggal, lalu LEFT JOIN tabel penjualan ke situ sebelum hitung running total.

Running total bisa dipisah per kota?

Bisa, pakai PARTITION BY. Tulis SUM(total) OVER (PARTITION BY kota ORDER BY tanggal). Akumulasinya bakal reset ke nol tiap ganti kota, jadi kamu dapat running total Jakarta sendiri, Surabaya sendiri, dan seterusnya. Ini yang paling sering dipakai buat bandingin kecepatan pertumbuhan antar wilayah dalam satu query.

Kenapa harus ada SUM dua kali di query-ku?

Karena kamu lagi gabungin agregasi biasa sama window function. SUM(total) yang di dalam ngerjain GROUP BY per tanggal, ngasilin omzet harian. SUM(...) OVER yang di luar ngambil hasil itu lalu ngakumulasinya. Kalau kamu nulis SUM(total) OVER doang tanpa GROUP BY, hasilnya jadi akumulasi per transaksi, bukan per hari.

Window function jalan di MySQL versi lama?

Nggak. Window function baru masuk MySQL di versi 8.0, rilis 2018. Kalau kamu masih pakai MySQL 5.7, kamu harus pakai cara lama — self-join atau variabel session, dua-duanya lebih lambat dan lebih ribet. PostgreSQL udah dukung window function sejak versi 8.4, jadi hampir semua instalasi PostgreSQL yang aktif sekarang aman.

Penutup

Yang perlu kamu inget:

  • SUM(x) OVER (ORDER BY tanggal) — itu inti running total-nya.
  • Kalau mau per hari, GROUP BY dulu, dan siap-siap lihat SUM(SUM(...)).
  • Tanggal bolong bikin grafik kamu bohong. LEFT JOIN ke tabel kalender.

Coba jalanin query pertamanya di data kamu sendiri hari ini. Sepuluh baris cukup buat lihat polanya.

Kalau OVER masih terasa asing, mulai dari definisi window function di glossary — sekali paham konsepnya, RANK dan LAG jadi gampang.

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