Menghitung Pertumbuhan Week over Week di SQL (2026)
TL;DR
Pertumbuhan week over week (WoW) di SQL dihitung dengan ngebandingin nilai minggu ini sama nilai minggu sebelumnya, pakai fungsi window LAG(). Langkahnya: kelompokkan data per minggu pakai DATE_TRUNC('week', tanggal), ambil nilai minggu lalu pakai LAG() OVER (ORDER BY minggu), lalu hitung (sekarang - lalu) / lalu * 100. Hasilnya persen naik-turun antar minggu yang berurutan.
Pertumbuhan week over week di SQL dihitung dengan ngebandingin angka minggu ini sama minggu sebelumnya. Rumusnya (minggu_ini - minggu_lalu) / minggu_lalu * 100, dan alat utamanya fungsi window LAG().
Metrik ini kepakai buat mantau tren jangka pendek. Omzet, jumlah order, user aktif, semua bisa dilihat naik-turunnya per minggu tanpa nunggu akhir bulan.
Aku bakal tunjukin caranya dari nol: agregasi mingguan dulu, baru ambil nilai minggu lalu, terakhir hitung persennya. Semua query di sini pakai sintaks PostgreSQL, tapi logikanya sama di MySQL 8 dan BigQuery.
Apa itu week over week di SQL?
Week over week (WoW) adalah perbandingan satu metrik antara minggu berjalan dan minggu tepat sebelumnya. Hasilnya berupa persen naik atau turun. Bedanya sama year over year, WoW fokus ke pergerakan mingguan yang lebih peka buat ngedeteksi perubahan cepat, kayak efek promo atau libur.
Buat ngitungnya, kamu butuh dua hal: data yang udah dikelompokkan per minggu, dan cara ngambil nilai minggu sebelumnya di baris yang sama. Yang kedua ini kerjaan LAG(), fungsi window yang ngintip baris sebelumnya. Konsep dasarnya aku bahas di glosarium window function.
Gimana cara kelompokkan data per minggu?
Pakai DATE_TRUNC('week', tanggal) buat mundurin tiap tanggal ke awal minggunya. Di PostgreSQL, minggu mulai hari Senin. Setelah itu, GROUP BY hasil truncate-nya dan jumlahin metrik yang kamu mau. Ini ngubah data transaksi harian jadi satu baris per minggu.
SELECT
DATE_TRUNC('week', tanggal_order) AS minggu,
SUM(total) AS omzet
FROM orders
GROUP BY 1
ORDER BY 1;
Hasilnya satu baris per minggu dengan total omzetnya. Baris inilah yang jadi bahan buat langkah berikutnya. Kalau kamu belum familiar sama teknik ngelompokin per rentang waktu, aku bahas lebih lengkap di artikel date bucketing.
Gimana cara ambil nilai minggu sebelumnya pakai LAG?
LAG(kolom) ngambil nilai dari baris sebelumnya dalam urutan yang kamu tentuin. Dengan OVER (ORDER BY minggu), dia ngintip omzet minggu tepat sebelum baris sekarang. Baris pertama gak punya minggu sebelumnya, jadi hasilnya NULL.
WITH mingguan AS (
SELECT
DATE_TRUNC('week', tanggal_order) AS minggu,
SUM(total) AS omzet
FROM orders
GROUP BY 1
)
SELECT
minggu,
omzet,
LAG(omzet) OVER (ORDER BY minggu) AS omzet_minggu_lalu
FROM mingguan
ORDER BY minggu;
Sekarang tiap baris punya dua angka bersebelahan: omzet minggu ini dan minggu lalu. Tinggal dihitung selisihnya.
Gimana cara hitung persen pertumbuhannya?
Bungkus query tadi jadi CTE, lalu hitung (omzet - omzet_minggu_lalu) / omzet_minggu_lalu * 100. Pakai ROUND() biar rapi dan NULLIF() buat jaga-jaga kalau omzet minggu lalu nol, biar gak error dibagi nol.
WITH mingguan AS (
SELECT
DATE_TRUNC('week', tanggal_order) AS minggu,
SUM(total) AS omzet
FROM orders
GROUP BY 1
),
banding AS (
SELECT
minggu,
omzet,
LAG(omzet) OVER (ORDER BY minggu) AS omzet_lalu
FROM mingguan
)
SELECT
minggu,
omzet,
omzet_lalu,
ROUND((omzet - omzet_lalu) * 100.0 / NULLIF(omzet_lalu, 0), 1) AS wow_persen
FROM banding
ORDER BY minggu;
Kolom wow_persen ngasih angka kayak 18,4 (naik) atau -7,2 (turun). Itu pertumbuhan week over week kamu.
Contoh kasus: omzet mingguan toko_berkah
Toko_berkah jualan online, dan aku narik omzet 6 minggu terakhir buat lihat tren. Hasilnya kayak gini:
| Minggu | Omzet | WoW % |
|---|---|---|
| 2 Jun | Rp 42.100.000 | n/a |
| 9 Jun | Rp 48.700.000 | +15,7% |
| 16 Jun | Rp 45.200.000 | -7,2% |
| 23 Jun | Rp 61.800.000 | +36,7% |
| 30 Jun | Rp 52.300.000 | -15,4% |
| 7 Jul | Rp 55.900.000 | +6,9% |
Yang menarik: lonjakan 36,7% di minggu 23 Juni pas banget sama gajian akhir bulan. Aku cek 3 bulan ke belakang, dan pola ini konsisten. Minggu yang ngandung tanggal 25-31 rata-rata 28% lebih tinggi dari minggu awal bulan. Temuan ini yang bikin tim marketing mindahin jadwal promo ke minggu keempat.
Tanpa kolom WoW, lonjakan ini gampang kelewat karena angka absolutnya keliatan wajar. Persennya yang bikin polanya kebaca.
Kesalahan umum waktu hitung WoW
Lupa ORDER BY di dalam LAG. Tanpa ORDER BY minggu, LAG gak tahu mana baris "sebelumnya". Hasilnya bisa ngambil minggu acak. Urutan di window itu wajib, beda sama ORDER BY di akhir query.
Minggu yang kosong bikin lompatan. Kalau ada minggu tanpa transaksi, barisnya hilang dari hasil GROUP BY. LAG bakal ngebandingin dua minggu yang gak berurutan. Buat data yang perlu presisi, bikin dulu deret tanggal lengkap lalu LEFT JOIN.
Dibagi nol. Kalau omzet minggu lalu nol, pembagian langsung error. Selalu bungkus penyebut pakai NULLIF(omzet_lalu, 0).
Awal minggu beda antar database. PostgreSQL mulai Senin, sebagian tool BI mulai Minggu. Kalau angkamu beda sama dashboard, cek dulu definisi awal minggu di kedua sisi.
FAQ
Apa bedanya LAG dan LEAD di SQL?
LAG ngambil nilai dari baris sebelumnya, LEAD ngambil dari baris sesudahnya. Buat week over week, kamu butuh LAG karena mau ngebandingin minggu ini sama minggu lalu yang posisinya di atas. LEAD kepakai kalau kamu mau ngeliat ke depan, misalnya berapa order minggu depan dibanding sekarang. Keduanya fungsi window dengan sintaks yang mirip.
Gimana kalau ada minggu yang gak ada datanya?
Minggu tanpa transaksi bakal hilang dari hasil GROUP BY, dan itu bikin LAG ngebandingin dua minggu yang gak nyambung. Solusinya, bikin dulu tabel deret semua minggu pakai generate_series, lalu LEFT JOIN ke data kamu. Minggu kosong bakal keisi nol, jadi perhitungan WoW-nya tetap akurat dan gak ada lompatan.
Apakah WoW bisa dihitung tanpa window function?
Bisa, tapi ribet. Kamu mesti self join tabel mingguan ke dirinya sendiri dengan syarat minggu selisih 7 hari. Query-nya lebih panjang dan lebih lambat di data besar. LAG jauh lebih ringkas dan gampang dibaca. Kalau database kamu dukung window function, dan hampir semua yang modern dukung, pakai LAG aja.
Kenapa hasil WoW minggu pertama selalu kosong?
Karena minggu pertama gak punya minggu sebelumnya buat dibandingin. LAG ngembaliin NULL di baris paling awal, jadi perhitungan persennya juga NULL. Ini normal dan bukan error. Kalau mau, kamu bisa tampilin sebagai strip atau nol pakai COALESCE, tapi secara logika emang gak ada angka pembandingnya.
Bisa gak WoW dipecah per produk atau kota?
Bisa, tambahin PARTITION BY di dalam window. Contohnya LAG(omzet) OVER (PARTITION BY kota ORDER BY minggu). Dengan gitu, LAG ngambil minggu lalu dalam kota yang sama, gak nyampur antar kota. Ini berguna kalau kamu mau bandingin tren mingguan Jakarta sama Surabaya secara terpisah dalam satu query.
Penutup
Ringkasan cara hitung week over week di SQL:
- Kelompokkan data per minggu pakai
DATE_TRUNC('week', tanggal) - Ambil nilai minggu lalu pakai
LAG() OVER (ORDER BY minggu) - Hitung
(sekarang - lalu) / lalu * 100, jaga pembagian nol pakai NULLIF
Dokumentasi lengkap fungsi window ada di dokumentasi PostgreSQL. Kalau kamu mau lanjut ke metrik waktu lain, baca cara hitung YTD, QTD, dan MTD di SQL, atau pelajari dasar window function dulu biar makin lancar.
Mau praktek langsung? Mulai latihan SQL gratis
Latihan interaktif, langsung di browser.
Artikel terkait
Composite Index di SQL: Cara Kerja dan Urutan Kolom
Composite index itu index atas beberapa kolom sekaligus. Urutan kolomnya nentuin query mana yang kebantu, lewat aturan leftmost prefix.
Menghitung Stickiness (DAU/MAU) di SQL
Stickiness ngukur seberapa sering user balik lagi. Ini cara hitung DAU, MAU, dan rasio stickiness pakai SQL, plus contoh aplikasi UMKM.
Menghitung DAU dan MAU dengan SQL
DAU dan MAU dua metrik wajib buat produk digital. Ini cara hitungnya pakai SQL, lengkap query DISTINCT, per bulan, sampai rasio stickiness.