Panduan Praktis dari Nol sampai Bisa — Bisa Langsung Dicoba di Google Colab / VSCode
TL;DR (buat yang buru-buru) Window function itu cara SQL untuk “mengintip” baris lain tanpa menghilangkan baris aslinya (beda sama
GROUP BYyang meringkas). Empat fungsi paling sering dipakai:ROW_NUMBER()(nomor urut unik),RANK()(peringkat, bisa kembar & ada lompatan),LAG()(lihat baris sebelumnya),LEAD()(lihat baris berikutnya).
1. Mengapa Window Function SQL Itu Penting?
Bayangkan kamu punya data penjualan per bulan, terus disuruh bos:
- “Ranking-in dong sales terbaik tiap cabang!”
- “Bandingin omzet bulan ini vs bulan lalu, growth-nya berapa persen?”
- “Ambil 1 transaksi terakhir tiap customer.”
Kalau pakai GROUP BY biasa, baris-baris detail kamu akan hilang karena diringkas. Di sinilah window function menyelamatkan hidup — dia menghitung sesuatu (ranking, rata-rata, nilai baris sebelah) tanpa meringkas data aslinya.
┌─────────────────────────────────────────────────┐
│ GROUP BY → banyak baris jadi sedikit │
│ WINDOW FUNCTION → banyak baris tetap banyak, │
│ tapi tiap baris "sadar" │
│ posisi & tetangganya │
└─────────────────────────────────────────────────┘
2. Anatomi Syntax-nya
Semua window function punya bentuk umum begini:
FUNGSI() OVER (
PARTITION BY kolom_pengelompok -- opsional, seperti "GROUP BY versi window"
ORDER BY kolom_urutan -- wajib untuk RANK, ROW_NUMBER, LAG, LEAD
)
| Bagian | Fungsi |
|---|---|
PARTITION BY | Membagi data jadi kelompok-kelompok kecil (mis. per cabang, per customer) |
ORDER BY | Menentukan urutan baris di dalam tiap kelompok (mis. dari omzet tertinggi) |
OVER (...) | “Jendela” tempat fungsi tersebut beroperasi — inilah asal nama window function |
3. Siapkan Dataset — Bisa Jalan di Google Colab MAUPUN VSCode
Kita pakai SQLite via Python supaya kamu nggak perlu install database server. Kode ini identik persis di Colab dan VSCode (asal Python & pandas terinstall) Sihlakan gunakan Dataset ini untuk melakukan praktek langsung !
import sqlite3
import pandas as pd
# Buat koneksi database in-memory
conn = sqlite3.connect(":memory:")
cur = conn.cursor()
# Buat tabel penjualan
cur.execute("""
CREATE TABLE penjualan (
id INTEGER PRIMARY KEY,
cabang TEXT,
sales TEXT,
bulan TEXT,
omzet INTEGER
)
""")
data = [
(1, 'Jakarta', 'Andi', '2026-01', 15000000),
(2, 'Jakarta', 'Andi', '2026-02', 18000000),
(3, 'Jakarta', 'Budi', '2026-01', 22000000),
(4, 'Jakarta', 'Budi', '2026-02', 19000000),
(5, 'Bandung', 'Citra', '2026-01', 12000000),
(6, 'Bandung', 'Citra', '2026-02', 25000000),
(7, 'Bandung', 'Dewi', '2026-01', 22000000),
(8, 'Bandung', 'Dewi', '2026-02', 22000000),
]
cur.executemany("INSERT INTO penjualan VALUES (?,?,?,?,?)", data)
conn.commit()
pd.read_sql("SELECT * FROM penjualan", conn)
Nanti hasilnya seperti ini juga sudah salin kode di atas :

Catatan VSCode: pastikan sudah
pip install pandasdi terminal, lalu jalankan file.pyini via Jupyter extension ataupython nama_file.py(untuk versi non-Jupyter, ganti baris terakhir denganprint(...)).
Jika kamu ingin melatih Validasi Query SQL untuk melanjutkan tutorial ini ketingkat yang lebih tinggi sihlakan kunjungi artikel dibawah ini :
4. ROW_NUMBER() — “Nomor Antrean”
Memberi nomor urut unik, 1, 2, 3, … tanpa ada yang kembar, meskipun nilainya sama persis.
Mengapa harus pakai ROW_NUMBER()? Karena ini cara paling gampang untuk memberi nomor urut mutlak pada tiap baris di dalam kelompoknya — cocok kalau kamu butuh kepastian satu baris “juara” tanpa toleransi nilai kembar.
query = """
SELECT
cabang,
sales,
bulan,
omzet,
ROW_NUMBER() OVER (
PARTITION BY cabang
ORDER BY omzet DESC
) AS no_urut
FROM penjualan;
"""
pd.read_sql(query, conn)
query = """
SELECT
cabang, sales, bulan, omzet,
ROW_NUMBER() OVER (PARTITION BY cabang ORDER BY omzet DESC) AS no_urut
FROM penjualan;
"""
pd.read_sql(query, conn)
ini hasilnya jika sudah di salin :


Kapan dipakai? Ambil “Top-1 per kelompok” (misal: transaksi terakhir tiap customer, produk terlaris per kategori).
5. RANK() — “Peringkat Lomba”
Mirip ROW_NUMBER(), tapi kalau nilainya sama, peringkatnya sama juga — dan nomor berikutnya melompat.
Mengapa RANK() beda dari ROW_NUMBER()? Karena di dunia nyata, dua orang bisa saja punya nilai yang sama persis (misalnya omzet kembar). RANK() menjawab pertanyaan “mengapa dua sales ini pantas dapat peringkat yang sama?” dengan cara yang adil secara statistik.
query = """
SELECT
cabang,
sales,
omzet,
RANK() OVER (
PARTITION BY cabang
ORDER BY omzet DESC
) AS peringkat
FROM penjualan
WHERE bulan = '2026-02';
"""
pd.read_sql(query, conn)

📊 Ilustrasi bedanya dengan ROW_NUMBER:
| omzet | ROW_NUMBER() | RANK() | DENSE_RANK() |
|---|---|---|---|
| 25.000.000 | 1 | 1 | 1 |
| 22.000.000 | 2 | 2 | 2 |
| 22.000.000 | 3 | 2 (kembar) | 2 (kembar) |
| 19.000.000 | 4 | 4 (lompat ke 4) | 3 (tidak lompat) |
6. LAG() — “Lihat ke Belakang”
Mengambil nilai dari baris sebelumnya dalam urutan yang sama. Paling populer untuk hitung growth month-over-month.
Mengapa LAG() penting untuk analisis tren? Karena mengapa sebuah angka naik atau turun baru bisa dijawab kalau kita bisa membandingkannya dengan nilai periode sebelumnya — dan itulah tepatnya yang dilakukan LAG().
query = """
SELECT
cabang,
sales,
bulan,
omzet,
LAG(omzet, 1) OVER (
PARTITION BY sales
ORDER BY bulan
) AS omzet_bulan_lalu,
ROUND(
(omzet - LAG(omzet, 1) OVER (PARTITION BY sales ORDER BY bulan)) * 100.0
/ LAG(omzet, 1) OVER (PARTITION BY sales ORDER BY bulan), 2
) AS growth_persen
FROM penjualan;
"""
pd.read_sql(query, conn)
🎯 Kapan dipakai? Analisis tren (growth, churn), bandingkan nilai sekarang vs periode sebelumnya.
Mau Kuasai Window Function SQL: RANK, ROW_NUMBER, LAG, LEAD Sampai Bisa Praktik Langsung?
Materi ini juga kami ajarkan langsung di kelas Edusoft Center, dibimbing mentor, sampai kamu bisa praktik nyata — bukan cuma baca teori.
Tanya Kursus via WhatsApp Lihat contoh project nyata dari siswa kami →
7. LEAD() — “Lihat ke Depan”
Kebalikan dari LAG() — mengintip nilai baris berikutnya.
Mengapa perlu LEAD()? Mengapa tidak cukup hanya melihat ke belakang? Karena banyak analisis bisnis butuh jawaban atas “apa yang terjadi setelahnya” — misalnya mengapa transaksi menurun setelah promo berakhir. LEAD() membantu menjawab pertanyaan “mengapa” yang berorientasi ke masa depan itu.
query = """
SELECT
cabang,
sales,
bulan,
omzet,
LEAD(omzet, 1) OVER (
PARTITION BY sales
ORDER BY bulan
) AS omzet_bulan_depan
FROM penjualan;
"""
pd.read_sql(query, conn)
🎯 Kapan dipakai? Prediksi sederhana, cari tahu “apa yang terjadi setelah event X” (mis. transaksi setelah promo).
8. Studi Kasus Gabungan — “Laporan Kinerja Sales”
Ini contoh nyata menggabungkan keempatnya sekaligus, khas laporan bisnis:
query = """
SELECT
cabang,
sales,
bulan,
omzet,
RANK() OVER (PARTITION BY bulan ORDER BY omzet DESC) AS ranking_bulan_ini,
ROW_NUMBER() OVER (PARTITION BY sales ORDER BY bulan) AS urutan_transaksi,
LAG(omzet) OVER (PARTITION BY sales ORDER BY bulan) AS omzet_lalu,
LEAD(omzet) OVER (PARTITION BY sales ORDER BY bulan) AS omzet_depan
FROM penjualan
ORDER BY bulan, ranking_bulan_ini;
"""
pd.read_sql(query, conn)query = """
SELECT
cabang, sales, bulan, omzet,
RANK() OVER (PARTITION BY bulan ORDER BY omzet DESC) AS ranking_bulan_ini,
ROW_NUMBER() OVER (PARTITION BY sales ORDER BY bulan) AS urutan_transaksi,
LAG(omzet) OVER (PARTITION BY sales ORDER BY bulan) AS omzet_lalu,
LEAD(omzet) OVER (PARTITION BY sales ORDER BY bulan) AS omzet_depan
FROM penjualan
ORDER BY bulan, ranking_bulan_ini;
"""
pd.read_sql(query, conn)
ini untuk hasil codenya jika sudah di salin :


9. Cheat Sheet — Simpan buat Contekan
| Fungsi | Mengintip Kemana? | Nilai Kembar? | Contoh Use-Case |
|---|---|---|---|
ROW_NUMBER() | Nomor urut diri sendiri | ❌ Selalu unik | Ambil transaksi terbaru per user |
RANK() | Peringkat diri sendiri | ✅ Kembar + lompat | Ranking juara lomba |
DENSE_RANK() | Peringkat diri sendiri | ✅ Kembar, tanpa lompat | Level/tier customer |
LAG(kolom, n) | n baris ke belakang | — | Growth bulan ini vs lalu |
LEAD(kolom, n) | n baris ke depan | — | Selisih ke transaksi berikutnya |
🔑 Rumus Sakti:
FUNGSI() OVER (PARTITION BY ... ORDER BY ...)
↑ ↑
"per kelompok" "urutan dalam kelompok"
10. Latihan Mandiri (Coba Sendiri!)
Pakai dataset penjualan di atas, coba jawab pertanyaan ini dengan window function:
- 🥇 Siapa sales dengan omzet tertinggi di tiap bulan (pakai
RANK())? - 📈 Cabang mana yang omzetnya naik dari Januari ke Februari (pakai
LAG())? - 🎯 Ambil hanya transaksi pertama tiap sales (pakai
ROW_NUMBER() = 1di subquery/CTE).
WITH ranked AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY sales ORDER BY bulan) AS rn
FROM penjualan
)
SELECT * FROM ranked WHERE rn = 1;
</details>
11. Mengapa Harus Latihan Pakai Google Colab atau VSCode?
Banyak yang belajar SQL cuma modal baca teori atau nonton video — padahal window function itu jenis materi yang baru “klik” di kepala kalau dicoba langsung. Berikut alasan mengapa dua tools ini jadi pilihan terbaik buat latihan:
| Alasan | Penjelasan |
|---|---|
| 🆓 Gratis & tanpa install ribet | Google Colab jalan 100% di browser, tanpa perlu install database server sama sekali. VSCode juga gratis dan ringan. |
| ⚡ Bisa langsung lihat hasil query | Nggak perlu tools tambahan seperti DBeaver/pgAdmin — cukup pandas.read_sql(), hasil tabelnya langsung muncul rapi di bawah cell. |
| 🔁 Iterasi cepat = belajar lebih efektif | Mengapa ini penting? Karena begitu ubah ORDER BY atau PARTITION BY, kamu bisa langsung re-run dan lihat efeknya detik itu juga — bukan nunggu proses deploy atau setup server. |
| ☁️ Colab: tidak butuh spek laptop tinggi | Semua proses jalan di server Google, jadi laptop dengan RAM kecil pun tetap lancar buat eksperimen dataset besar. |
| 🖥️ VSCode: mendekati workflow kerja nyata | Kalau tujuannya melamar kerja sebagai data analyst, latihan di VSCode membiasakan kamu dengan environment yang mirip dipakai di dunia industri (extension Jupyter, integrasi Git, dsb). |
| 📁 Mudah disimpan & dibagikan | Notebook Colab bisa langsung di-share via link Google Drive, sementara file .ipynb di VSCode gampang di-push ke GitHub sebagai portofolio. |
💡 Kesimpulan singkat: Mengapa harus praktik, bukan cuma baca? Karena window function penuh dengan detail kecil (urutan
PARTITION BYvsORDER BY, efekRANKvsDENSE_RANK, dll) yang jauh lebih cepat dipahami lewat trial-and-error langsung, dibanding hanya membayangkan hasilnya di kepala.
12. Cara Menjalankan di Google Colab vs VSCode
| Langkah | Google Colab | VSCode |
|---|---|---|
| Install library | Sudah tersedia (sqlite3, pandas bawaan) | pip install pandas |
| Buat file | New Notebook (.ipynb) | Buat file .ipynb + install ekstensi Jupyter |
| Jalankan | Klik ▶️ tiap cell | Run Cell di atas tiap blok kode |
| Lihat hasil tabel | Otomatis muncul di bawah cell | Otomatis muncul di panel output |
✅ Tips: Kalau mau pakai database sungguhan (PostgreSQL/MySQL), tinggal ganti
sqlite3.connect(":memory:")dengan koneksi library sepertipsycopg2ataumysql-connector-python— syntax window function-nya hampir sama persis.
Penutup
Window function adalah salah satu skill SQL yang paling sering dites di interview data analyst/data scientist — karena satu query bisa menggantikan puluhan baris kode Python untuk hal seperti ranking, growth rate, atau moving comparison.
Ingat urutan belajarnya: PARTITION BY (kelompokkan) → ORDER BY (urutkan) → pilih fungsi (ROW_NUMBER/RANK/LAG/LEAD) sesuai kebutuhan.
Selamat mencoba, semoga query-mu makin smooth seperti window function-nya! 🪟✨
Ditulis dengan contoh dataset fiktif untuk keperluan pembelajaran. Semua kode teruji dan siap dijalankan langsung di Google Colab maupun VSCode.
Penulis
Junior Alfredo Benerd Setiawan
Mau Kuasai Window Function SQL: RANK, ROW_NUMBER, LAG, LEAD Sampai Bisa Praktik Langsung?
Materi ini juga kami ajarkan langsung di kelas Edusoft Center, dibimbing mentor, sampai kamu bisa praktik nyata — bukan cuma baca teori.
Tanya Kursus via WhatsApp Lihat contoh project nyata dari siswa kami →
