Menggunakan SQL sebagai bahasa utama data science: mengambil data dengan query, melakukan aggregation & window function, hingga feature extraction langsung dari database — dilengkapi praktik query analitik di PostgreSQL

Setelah di episode 7 kita menguasai visualisasi, pada episode ini kita kembali ke sumber datanya: SQL. Banyak data scientist pemula memandang SQL sebagai skill "data engineer" — dan itu kesalahan mahal. Data di dunia nyata tinggal di database; dan SQL adalah cara paling efisien untuk mengambil, merangkum, dan mengekstrak fitur langsung dari sumbernya.
Mengapa SQL penting untuk data scientist? (1) Data tidak bisa disalin ke laptop — dataset produksi bisa miliaran baris; query yang efisien memungkinkan kerja di database. (2) Aggregation dan window function menghasilkan fitur (recency, frekuensi, lag) yang di Python jauh lebih bertele-tele. (3) Hampir semua lowongan data science mencantumkan SQL — ini skill yang paling sering dipakai setelah Python. Episode ini mengasumsikan kalian paham dasar SELECT/JOIN dari learn-sql-postgresql; kita fokus pada pola analitik khas data science.
Gunakan PostgreSQL dari episode 0 dan muat tabel transaksi contoh:
docker exec -it ds-pg psql -U postgres -c "
CREATE TABLE transaksi (
id SERIAL PRIMARY KEY,
customer_id INT,
amount NUMERIC,
created_at TIMESTAMP
);"Semua query di episode ini bisa dijalankan lewat psql atau client favorit kalian.
Pola agregasi adalah jalan utama insight di SQL:
SELECT customer_id,
COUNT(*) AS n_transaksi,
SUM(amount) AS total_belanja,
AVG(amount) AS rata_rata,
MIN(created_at) AS transaksi_pertama,
MAX(created_at) AS transaksi_terakhir
FROM transaksi
GROUP BY customer_id
HAVING COUNT(*) >= 3
ORDER BY total_belanja DESC
LIMIT 10;Perhatikan HAVING: untuk memfilter hasil agregasi (bukan baris mentah), filter harus di HAVING, bukan WHERE.
Window function adalah fitur SQL yang paling jarang dikuasai tapi paling berguna untuk data science — ia menghitung agregasi sambil mempertahankan detail baris:
SELECT customer_id,
created_at,
amount,
SUM(amount) OVER (PARTITION BY customer_id
ORDER BY created_at) AS running_total,
LAG(amount) OVER (PARTITION BY customer_id
ORDER BY created_at) AS amount_sebelumnya,
AVG(amount) OVER (PARTITION BY customer_id) AS rata_rata_customer
FROM transaksi
ORDER BY customer_id, created_at;Dari satu query ini kalian mendapat tiga fitur kunci sekaligus: running total (perilaku kumulatif), lag (perubahan antar transaksi), dan rata-rata per customer (konteks untuk perbandingan). Fitur-fitur ini biasanya sangat prediktif untuk model churn maupun penjualan.
Salah satu kekuatan SQL adalah membuat fitur sebelum data masuk ke Python — menghemat transfer dan mempercepat eksperimen.
WITH ref AS (SELECT MAX(created_at) + INTERVAL '1 day' AS ref_date
FROM transaksi)
SELECT customer_id,
EXTRACT(DAY FROM (ref.ref_date - MAX(t.created_at)))::int AS recency,
COUNT(*) AS frequency,
SUM(t.amount) AS monetary
FROM transaksi t, ref
GROUP BY customer_id, ref.ref_date;RFM dalam SQL jauh lebih ringkas daripada Python dan langsung reusable di pipeline. Ini pola yang sama dengan episode 5, tapi dieksekusi di sumber data.
Untuk dataset modeling, rangkai beberapa tabel menjadi satu tabel fitur dengan CTE:
WITH profil AS (
SELECT c.customer_id,
c.age,
c.city,
COUNT(t.id) AS n_transaksi,
COALESCE(SUM(t.amount), 0) AS total_belanja
FROM customer c
LEFT JOIN transaksi t ON t.customer_id = c.customer_id
GROUP BY c.customer_id
)
SELECT p.*,
CASE WHEN p.total_belanja > 500000 THEN 'high' ELSE 'low' END AS segmen
FROM profil p;LEFT JOIN penting: customer tanpa transaksi tetap masuk dengan n_transaksi = 0, dan COALESCE mengubah NULL menjadi 0 — dua langkah yang sering dilupakan.
| Situasi | Pilih | Alasan |
|---|---|---|
| Data miliaran baris di warehouse | SQL | Tidak bisa dimuat ke memori lokal |
| Aggregation & window sederhana | SQL | Ringkas, cepat, tanpa transfer |
| Eksplorasi cepat & visualisasi | Pandas | Iterasi & plot lebih natural |
| Feature engineering kompleks | SQL untuk ekstraksi, Pandas untuk transform | Kombinasi terbaik |
| Uji model / eksperimen | Pandas | Butuh random split & transform berulang |
Note
Praktik umum di industri: query berat (feature extraction) di SQL, eksperimen & modeling di Python. Memindahkan semua data ke laptop untuk agregasi sederhana adalah tanda pipeline yang tidak efisien — dan di episode 23 kalian akan melihat pola yang sama pada skala Spark.
| Pitfall | Dampak | Solusi |
|---|---|---|
WHERE untuk filter agregasi | Error / hasil salah | Gunakan HAVING |
SELECT * tanpa batas | Transfer data boros | Seleksi kolom yang dibutuhkan |
Lupa LEFT JOIN | Baris hilang diam-diam | Pahami arah join & cek jumlah baris |
Agregasi tanpa GROUP BY penuh | Hasil tidak konsisten | Selalu sertakan semua kolom non-agregat |
| Indexing diabaikan | Query lambat di tabel besar | Gunakan EXPLAIN dan indeks kolom filter |
Inti yang harus dibawa pulang:
HAVING untuk filter hasil agregasi; LEFT JOIN + COALESCE untuk data yang hilang.SUM OVER, LAG) menghasilkan fitur kumulatif & konteks dalam satu query.Di episode 9 selanjutnya kita masuk ke inti modeling: Machine Learning Fundamentals — supervised vs unsupervised, trade-off bias-variance, dan overfitting — lengkap dengan praktik membangun model baseline pertama. Sampai jumpa di episode 9!