Cara Cari Produk Terlaris dan Customer Terbesar Pakai SQL Top-N
Produk terlaris dan customer dengan belanja terbesar bisa dicari langsung dari database pakai kombinasi GROUP BY, ORDER BY, LIMIT, dan RANK() — teknik yang biasa disebut Top-N Analysis. Nggak perlu tarik semua data ke aplikasi dulu, query-nya bisa langsung jalan di database. Berikut cara praktiknya, lengkap dengan alasan kenapa saya pilih pendekatan window function dibanding cuma pakai LIMIT biasa.
Saat saya pertama kali dapet request dari tim bisnis “produk apa yang paling laris bulan ini?”, saya awalnya cuma pakai ORDER BY … LIMIT 5. Tapi begitu ada pertanyaan lanjutan “kalau per kategori gimana?”, query itu jadi nggak cukup — di sinilah saya belajar kenapa Window Function kayak RANK() dibutuhkan.
💡 Kenapa Top-N Analysis Penting Dikuasai?
- Bantu tim bisnis fokus ke produk/customer yang paling berdampak.
- Jadi dasar buat keputusan stok, promosi, atau program loyalitas.
- Gampang dijalanin langsung di database, nggak perlu tarik semua data dulu.
- Bisa dikombinasikan sama filter waktu (bulanan, kuartalan, tahunan).
- Salah satu query paling sering muncul di dunia kerja data analyst.
Top-N Analysis Bisa Dipakai buat Kasus Apa Aja?
Top-N bukan cuma soal “produk terlaris” doang, tapi konsepnya bisa dipakai ke banyak kasus:
- Nentuin produk terlaris berdasarkan jumlah unit terjual.
- Nentuin produk paling menguntungkan berdasarkan total revenue.
- Nemuin customer dengan total belanja terbesar (biasa disebut VIP customer).
- Ranking cabang/toko dengan performa penjualan terbaik.
- Nyari Top-N per kategori, misalnya produk terlaris di tiap kategori barang.
Top-N Analysis ini sering banget dipakai diam-diam di balik proses berikut:
- Dashboard sales & e-commerce (best seller product)
- Program loyalitas customer (siapa yang dapet reward VIP)
- Laporan bulanan/kuartalan buat manajemen
- Rekomendasi produk berdasarkan tren terlaris
- Analisis performa cabang/toko/sales region
Apa Untungnya Pakai Top-N Query Langsung di SQL?
- Nggak perlu narik semua data ke aplikasi, cukup query langsung di database.
- Bisa digabung sama filter tanggal, kategori, atau region dengan mudah.
- Kalau pakai Window Function, bisa dapet Top-N per grup sekaligus dalam satu query.
- Hasilnya konsisten dan gampang dijadwalin buat laporan otomatis.
Apa yang Perlu Diperhatiin Sebelum Pakai Top-N?
- LIMIT doang kadang nggak adil kalau ada nilai yang sama persis (ties), makanya sering dipasangin sama RANK() atau DENSE_RANK().
- Salah pilih ukuran (quantity vs revenue) bisa ngasih hasil Top-N yang beda jauh maknanya.
- Query bisa lambat kalau tabelnya gede dan belum ada index di kolom yang di-JOIN/GROUP BY.
Buat referensi tambahan soal sintaks dasar LIMIT dan ORDER BY di SQL, kamu bisa cek dokumentasi SQL TOP/LIMIT di W3Schools.
Apa Saja Komponen Penting di Top-N Query?
Sebelum praktik, kenalan dulu sama fungsi-fungsi SQL yang bakal sering dipakai:
| Komponen | Artinya |
|---|---|
| GROUP BY | Ngelompokin data berdasarkan kolom tertentu (misal per produk/per customer) |
| SUM() / COUNT() | Ngitung total kuantitas, total revenue, atau jumlah transaksi per grup |
| ORDER BY … DESC | Ngurutin hasil dari yang paling besar ke paling kecil |
| LIMIT N | Ngambil cuma N baris teratas dari hasil yang udah diurutin |
| RANK() / DENSE_RANK() | Window function buat kasih peringkat, termasuk handle data yang nilainya sama (ties) |
| PARTITION BY | Bikin ranking terpisah per grup, misal Top-N per kategori produk |
1. Tools Apa yang Saya Pakai Buat Praktik Ini?
Saya pakai SQLite lewat Python (library sqlite3 yang udah bawaan Python) plus pandas biar hasil query-nya gampang dibaca dalam bentuk tabel, dijalanin di Google Colab. Alasannya, SQLite in-memory nggak perlu setup server dibanding install database beneran (MySQL/PostgreSQL) — selain itu, hasilnya reset otomatis tiap kali notebook dijalanin ulang, sehingga lebih praktis buat eksperimen berulang kali.
Import Library
import sqlite3
import pandas as pd2. Gimana Cara Siapin Dataset-nya?
Biar praktiknya nyambung sama kasus nyata, saya bikin dataset dummy toko online yang isinya 4 tabel: customers, products, orders, dan order_items. Kode di bawah ini bakal bikin database SQLite langsung di memory (nggak perlu install database beneran).
conn = sqlite3.connect(":memory:")
cur = conn.cursor()
cur.executescript("""
CREATE TABLE customers (
customer_id INTEGER PRIMARY KEY,
customer_name TEXT,
city TEXT
);
CREATE TABLE products (
product_id INTEGER PRIMARY KEY,
product_name TEXT,
category TEXT,
price INTEGER
);
CREATE TABLE orders (
order_id INTEGER PRIMARY KEY,
customer_id INTEGER,
order_date TEXT,
FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
);
CREATE TABLE order_items (
order_item_id INTEGER PRIMARY KEY,
order_id INTEGER,
product_id INTEGER,
quantity INTEGER,
FOREIGN KEY (order_id) REFERENCES orders(order_id),
FOREIGN KEY (product_id) REFERENCES products(product_id)
);
""")
conn.commit()
print("Tabel berhasil dibuat")Kolom yang penting diperhatiin di sini adalah quantity di tabel order_items (buat ngitung unit terjual) dan price di tabel products (buat ngitung revenue).
3. Data Dummy Apa yang Saya Pakai?
Sekarang saya masukin data contohnya. Ada 8 produk dari 3 kategori berbeda, 6 customer, dan beberapa order yang sengaja dibikin biar ada produk dan customer yang jelas-jelas “terlaris”.
cur.executescript("""
INSERT INTO customers (customer_id, customer_name, city) VALUES
(1, 'Andi Saputra', 'Semarang'),
(2, 'Budi Hartono', 'Jakarta'),
(3, 'Citra Dewi', 'Surabaya'),
(4, 'Dian Permata', 'Bandung'),
(5, 'Eka Wijaya', 'Semarang'),
(6, 'Fitri Ramadhani', 'Yogyakarta');
INSERT INTO products (product_id, product_name, category, price) VALUES
(1, 'Kaos Polos', 'Fashion', 75000),
(2, 'Celana Jeans', 'Fashion', 250000),
(3, 'Sepatu Sneakers', 'Fashion', 450000),
(4, 'Mouse Wireless', 'Elektronik', 120000),
(5, 'Keyboard Mekanik', 'Elektronik', 550000),
(6, 'Power Bank', 'Elektronik', 200000),
(7, 'Buku Novel', 'Buku', 85000),
(8, 'Notebook Catatan', 'Buku', 25000);
INSERT INTO orders (order_id, customer_id, order_date) VALUES
(1, 1, '2026-07-02'),
(2, 2, '2026-07-03'),
(3, 3, '2026-07-05'),
(4, 1, '2026-07-08'),
(5, 4, '2026-07-10'),
(6, 5, '2026-07-12'),
(7, 2, '2026-07-15'),
(8, 6, '2026-07-18'),
(9, 3, '2026-07-20'),
(10, 1, '2026-07-25');
INSERT INTO order_items (order_item_id, order_id, product_id, quantity) VALUES
(1, 1, 1, 3),
(2, 1, 4, 1),
(3, 2, 3, 1),
(4, 2, 6, 2),
(5, 3, 1, 5),
(6, 3, 7, 2),
(7, 4, 5, 1),
(8, 4, 4, 2),
(9, 5, 2, 2),
(10, 5, 8, 4),
(11, 6, 1, 10),
(12, 6, 6, 1),
(13, 7, 3, 2),
(14, 7, 5, 1),
(15, 8, 7, 3),
(16, 8, 1, 2),
(17, 9, 4, 3),
(18, 9, 3, 1),
(19, 10, 1, 8),
(20, 10, 6, 2);
""")
conn.commit()
print("Data berhasil diinsert")Biar makin ngerti:
- order_items ini tabel penghubung antara orders dan products, satu order bisa punya banyak item.
- Total unit terjual per produk = SUM(quantity) dari tabel order_items.
- Total revenue = SUM(quantity x price), jadi harus JOIN ke tabel products.
4. Produk Mana yang Paling Banyak Terjual Unitnya?
Pertanyaan paling dasar: produk mana yang paling banyak terjual unitnya? Saya pakai GROUP BY per produk, jumlahin quantity-nya, urutin dari yang terbesar, terus ambil 5 teratas pakai LIMIT.
Query Top-5 Produk Terlaris (by Unit)
query_top_produk_unit = """
SELECT
p.product_name,
p.category,
SUM(oi.quantity) AS total_unit_terjual
FROM order_items oi
JOIN products p ON oi.product_id = p.product_id
GROUP BY p.product_id, p.product_name, p.category
ORDER BY total_unit_terjual DESC
LIMIT 5;
"""
pd.read_sql_query(query_top_produk_unit, conn)Jalanin kode di atas, hasilnya bakal keluar tabel berisi 5 produk dengan total unit terjual paling banyak. Berikut hasil dari environment saya sendiri:

5. Kenapa Perlu Cek Top-N Berdasarkan Revenue Juga?
Kadang produk yang unitnya paling banyak terjual belum tentu yang paling nyumbang revenue. Makanya, saya itung juga versi revenue-nya, yaitu quantity dikaliin harga — soalnya kalau cuma lihat unit terjual, produk murah yang laku banyak bisa keliatan “terlaris” padahal kontribusinya ke omzet kecil.
Query Top-5 Produk Terlaris (by Revenue)
query_top_produk_revenue = """
SELECT
p.product_name,
p.category,
SUM(oi.quantity * p.price) AS total_revenue
FROM order_items oi
JOIN products p ON oi.product_id = p.product_id
GROUP BY p.product_id, p.product_name, p.category
ORDER BY total_revenue DESC
LIMIT 5;
"""
pd.read_sql_query(query_top_produk_revenue, conn)Waktu saya bandingin hasil query ini sama query sebelumnya, ranking-nya beneran bergeser — ada produk mahal yang unitnya sedikit tapi tetap nyumbang revenue besar. Berikut hasilnya:
Mau Kuasai Analisis Top-N dengan SQL: Produk Terlaris, Customer Terbesar 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 →

6. Siapa Customer dengan Belanja Terbesar?
Sekarang saya pindah fokus ke customer. Query-nya mirip, cuma sekarang saya JOIN tiga tabel sekaligus: customers, orders, dan order_items (plus products buat ambil harga).
Query Top-5 Customer Terbesar
query_top_customer = """
SELECT
c.customer_name,
c.city,
SUM(oi.quantity * p.price) AS total_belanja
FROM order_items oi
JOIN orders o ON oi.order_id = o.order_id
JOIN customers c ON o.customer_id = c.customer_id
JOIN products p ON oi.product_id = p.product_id
GROUP BY c.customer_id, c.customer_name, c.city
ORDER BY total_belanja DESC
LIMIT 5;
"""
pd.read_sql_query(query_top_customer, conn)Hasil query ini biasa dipakai buat nentuin siapa aja customer yang layak masuk program VIP atau dikasih penawaran khusus. Ini hasil dari data dummy yang saya jalankan:

7. Kenapa Saya Pilih Window Function Dibanding LIMIT Biasa buat Top-N per Kategori?
Nah, kalau saya mau tau produk terlaris di tiap kategori (bukan cuma top produk secara keseluruhan), LIMIT aja nggak cukup — karena LIMIT cuma motong hasil secara global, bukan per grup. Makanya, solusinya pakai Window Function kayak RANK(), dikombinasikan sama PARTITION BY biar ranking-nya dihitung ulang per kategori. Dibanding bikin query terpisah per kategori satu-satu, pendekatan ini saya pilih karena dengan PARTITION BY cukup satu query buat semua kategori sekaligus — lebih ringkas dan gampang di-maintain.
Query Top-2 Produk per Kategori (by Revenue)
query_top_per_kategori = """
WITH revenue_per_produk AS (
SELECT
p.product_name,
p.category,
SUM(oi.quantity * p.price) AS total_revenue
FROM order_items oi
JOIN products p ON oi.product_id = p.product_id
GROUP BY p.product_id, p.product_name, p.category
),
ranked AS (
SELECT
*,
RANK() OVER (
PARTITION BY category
ORDER BY total_revenue DESC
) AS rank_in_category
FROM revenue_per_produk
)
SELECT *
FROM ranked
WHERE rank_in_category <= 2
ORDER BY category, rank_in_category;
"""
pd.read_sql_query(query_top_per_kategori, conn)Biar makin ngerti:
- PARTITION BY category bikin ranking dihitung ulang dari 1 di tiap kategori, bukan ranking global.
- RANK() bakal ngasih peringkat yang sama kalau nilainya sama persis (ties), terus lompat ke peringkat berikutnya.
- DENSE_RANK() mirip RANK(), bedanya nggak ada peringkat yang “dilompatin” walau ada ties.
- ROW_NUMBER() selalu ngasih nomor urut unik, walau nilainya sama persis.

Gimana Cara Baca Hasil Top-N Analysis Ini?
Setelah semua query dijalanin, begini cara bacanya:
- Produk dengan unit terjual tinggi belum tentu penyumbang revenue terbesar, cek dua-duanya.
- Customer di Top-N belanja belum tentu paling sering order, bisa aja cuma sekali beli tapi nominalnya gede.
- Top-N per kategori berguna banget kalau kamu mau evaluasi tiap lini produk secara adil, bukan cuma produk yang paling “populer” secara umum.
- Kalau hasil Top-N-nya kepenuhan produk/customer yang sama terus tiap periode, itu bisa jadi sinyal buat evaluasi strategi produk lain yang kurang laku.
Biar Nggak Lupa, Ini Rangkumannya
| Fungsi | Kegunaan | Contoh |
|---|---|---|
| GROUP BY | Mengelompokkan data per produk/customer sebelum diagregasi. | GROUP BY p.product_id |
| SUM() | Menghitung total quantity atau total revenue per grup. | SUM(oi.quantity * p.price) |
| ORDER BY … DESC LIMIT N | Mengambil N baris teratas setelah data diurutkan. | ORDER BY total_revenue DESC LIMIT 5 |
| RANK() OVER (PARTITION BY …) | Membuat ranking terpisah per grup/kategori. | RANK() OVER (PARTITION BY category ORDER BY total_revenue DESC) |
Kalau Digabung, Alurnya Kayak Gini
⬇
🔗 JOIN Tabel yang Relevan
⬇
📦 GROUP BY per Produk / Customer / Kategori
⬇
📐 Hitung SUM(quantity) atau SUM(quantity x price)
⬇
🔽 ORDER BY … DESC + LIMIT N (atau RANK/PARTITION BY)
⬇
✅ Baca & Validasi Hasil Top-N
📝 Catatan Dikit
Kalau tabel kamu udah gede (jutaan baris), pastiin kolom yang dipakai buat JOIN dan GROUP BY (misalnya product_id, customer_id, order_id) udah punya index. Tanpa index, query Top-N bisa jadi lambat banget karena database harus nyisir semua baris satu-satu.
Abis Ini Belajar Apa Lagi?
🚀 Kalau udah pede sama Top-N Analysis, lanjut aja ke materi-materi ini:
- Window Function lanjutan: LAG(), LEAD(), NTILE()
- Analisis Cohort & Customer Retention pakai SQL
- RFM Analysis (Recency, Frequency, Monetary) buat segmentasi customer
- Time-based Analysis: Top-N per bulan/kuartal
- Optimasi Query dengan Index dan EXPLAIN QUERY PLAN
Materi-materi ini lanjutan yang natural setelah Top-N Analysis, dan sama-sama sering dipakai bareng-bareng di dunia kerja data analyst maupun data engineer.
Kesimpulan
Top-N Analysis itu salah satu skill SQL paling praktis dan paling sering dibutuhin di dunia kerja. Dengan kata lain, cuma pakai GROUP BY, SUM(), ORDER BY, dan LIMIT, kamu udah bisa jawab pertanyaan bisnis kayak “produk apa yang paling laris” atau “siapa customer paling loyal”. Namun, kalau butuh ranking per grup/kategori sekaligus, RANK() yang dikombinasikan sama PARTITION BY adalah pilihan yang lebih scalable dibanding bikin query terpisah satu-satu per kategori.
Kalau kamu udah nyaman sama query dasar ini, coba deh eksplor lebih jauh pakai Window Function biar bisa dapetin insight yang lebih detail, kayak Top-N per kategori atau per periode waktu.
🎉 Keren!
Sekarang kamu udah paham dasar-dasar Top-N Analysis, mulai dari nyari produk terlaris (by unit & revenue), customer terbesar, sampai Top-N per kategori pakai Window Function. Ini modal penting sebelum lanjut ke analisis SQL yang lebih kompleks.
Ditulis oleh Aziz Achmad Juniar
Mau Kuasai Analisis Top-N dengan SQL: Produk Terlaris, Customer Terbesar 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 →
