Retention Rate SQL: Ukur Pelanggan yang Balik Lagi
Blog/Tutorial SQL/Retention Rate SQL: Ukur Pelanggan yang Balik Lagi

Retention Rate SQL: Ukur Pelanggan yang Balik Lagi

BimaBima
·8 Mei 2026·9 menit baca

Penulis

Bima

Bima

Founder & Data Professional

Bagikan

TL;DR

Retention rate adalah persentase pelanggan dari satu periode yang balik lagi di periode berikutnya. Cara ngukurnya di SQL: kelompokin pelanggan berdasarkan bulan transaksi pertama (cohort), hitung selisih bulan tiap transaksi berikutnya, lalu bagi jumlah pelanggan aktif tiap bulan dengan ukuran cohort awalnya. Hasilnya cohort table, tabel segitiga yang nunjukin berapa persen pelanggan bertahan tiap bulan.

Retention rate adalah persentase pelanggan dari satu periode yang balik belanja lagi di periode berikutnya.

Angka ini yang bedain bisnis yang tumbuh dari bisnis yang cuma sibuk. Kamu bisa dapet 500 pelanggan baru tiap bulan dan tetap jalan di tempat — kalau 480 dari bulan lalu nggak pernah balik.

Ini cara bikin cohort retention table pakai SQL, dari nol sampai bisa dibaca.

Apa itu cohort retention?

Cohort retention adalah cara ngukur berapa persen pelanggan yang bertahan, dikelompokin berdasarkan kapan mereka pertama kali belanja. Kelompok itu namanya cohort. Pelanggan yang transaksi pertamanya di Januari masuk cohort Januari, dan mereka dilacak terus tiap bulan setelahnya.

Rumusnya:

retention_bulan_N = (pelanggan cohort yang aktif di bulan ke-N)
                    / (ukuran cohort di bulan ke-0) * 100

Perhatiin penyebutnya: selalu ukuran cohort awal. Bukan jumlah pelanggan bulan sebelumnya. Kalau kamu salah di sini, angka retention bisa kelihatan naik padahal pelanggannya terus berkurang.

Data apa yang dibutuhin?

Tiga kolom dari tabel transaksi.

transaksi
---------
pelanggan_id      integer
tanggal_transaksi date
status            text     -- 'selesai', 'batal', 'pending'

Itu doang. Nggak butuh tabel event, nggak butuh tracking pixel.

Langkah 1: Tentuin cohort tiap pelanggan

Cohort seseorang ditentuin sama bulan transaksi pertamanya.

WITH cohort_pelanggan AS (
  SELECT
    pelanggan_id,
    DATE_TRUNC('month', MIN(tanggal_transaksi)) AS cohort_bulan
  FROM transaksi
  WHERE status = 'selesai'
  GROUP BY pelanggan_id
)
SELECT * FROM cohort_pelanggan LIMIT 3;
pelanggan_id | cohort_bulan
-------------+-------------
         101 | 2026-01-01
         102 | 2026-01-01
         103 | 2026-03-01

Filter status = 'selesai' itu penting. Transaksi yang dibatalin nggak boleh nentuin cohort seseorang. Detail DATE_TRUNC ada di halaman fungsinya.

Langkah 2: Catat bulan aktif tiap pelanggan

Sekarang gabungin cohort tadi ke semua transaksi, dan ambil bulan-bulan mereka aktif.

aktivitas AS (
  SELECT DISTINCT
    t.pelanggan_id,
    c.cohort_bulan,
    DATE_TRUNC('month', t.tanggal_transaksi) AS bulan_aktif
  FROM transaksi t
  JOIN cohort_pelanggan c ON c.pelanggan_id = t.pelanggan_id
  WHERE t.status = 'selesai'
)

DISTINCT di sini nyegah pelanggan kehitung dua kali kalau dia belanja 5 kali dalam sebulan. Buat retention, yang kita hitung itu orangnya, bukan transaksinya.

Langkah 3: Hitung selisih bulan

Tiap baris aktivitas perlu tau ini bulan ke berapa sejak cohort-nya lahir.

hitung AS (
  SELECT
    cohort_bulan,
    (DATE_PART('year', bulan_aktif) - DATE_PART('year', cohort_bulan)) * 12
      + (DATE_PART('month', bulan_aktif) - DATE_PART('month', cohort_bulan)) AS bulan_ke,
    COUNT(DISTINCT pelanggan_id) AS pelanggan_aktif
  FROM aktivitas
  GROUP BY 1, 2
)

Rumus selisih bulannya kelihatan ribet, tapi logikanya sederhana: selisih tahun dikali 12, ditambah selisih bulan. Ini nyegah bug klasik di mana Januari 2027 dianggap 11 bulan sebelum Februari 2026.

Langkah 4: Bagi sama ukuran cohort awal

ukuran_cohort AS (
  SELECT cohort_bulan, pelanggan_aktif AS ukuran_awal
  FROM hitung
  WHERE bulan_ke = 0
)
SELECT
  h.cohort_bulan,
  h.bulan_ke,
  u.ukuran_awal,
  h.pelanggan_aktif,
  ROUND(100.0 * h.pelanggan_aktif / u.ukuran_awal, 1) AS retention_pct
FROM hitung h
JOIN ukuran_cohort u ON u.cohort_bulan = h.cohort_bulan
ORDER BY h.cohort_bulan, h.bulan_ke;

Angka 100.0 bukan 100 — di PostgreSQL, integer dibagi integer hasilnya integer. Lupa titik nol, semua retention kamu jadi 0%.

Contoh kasus: retention 6 bulan toko_berkah

Aku jalanin query lengkapnya di dataset toko_berkah. Ini cohort table-nya:

CohortUkuranBln 0Bln 1Bln 2Bln 3Bln 4Bln 5
Jan 2026214100%31,3%22,4%19,6%18,7%18,2%
Feb 2026187100%29,9%21,4%18,7%17,6%—
Mar 2026241100%36,5%27,8%24,9%——
Apr 2026198100%38,4%29,3%———
Mei 2026223100%37,7%————

Tiga hal yang langsung kebaca.

Bulan 1 selalu paling anjlok. Dari 100% ke sekitar 30-38%. Ini normal di e-commerce — kebanyakan orang beli sekali terus ilang.

Kurvanya mendatar setelah bulan 2. Cohort Januari turun dari 22,4% ke 18,2% dalam empat bulan. Yang bertahan sampai bulan 2 itu pelanggan beneran, dan mereka cenderung nempel.

Cohort Maret ke atas jauh lebih baik. Retention bulan-1 naik dari 29,9% (Feb) ke 36,5% (Mar) dan 38,4% (Apr). Lompatan 8,5 poin persentase itu gede.

Ternyata program poin loyalitas diluncurin awal Maret. Cohort table-nya nangkep efeknya dengan bersih, tanpa perlu A/B test.

Ini yang bikin cohort analysis kepake: dia misahin efek perubahan produk dari efek musiman. Kalau kamu cuma lihat total pelanggan aktif per bulan, kenaikan itu bakal ketutup sama pertumbuhan pelanggan baru.

Mau lanjut segmentasi siapa yang bertahan? Gabungin sama RFM analysis di SQL.

Kesalahan umum waktu ngitung retention

1. Penyebutnya salah. Bagi sama jumlah pelanggan bulan sebelumnya, bukan sama ukuran cohort awal. Ini bikin angka retention kelihatan naik terus padahal pelanggannya makin habis.

2. Lupa 100.0 di pembagian. Integer dibagi integer di PostgreSQL hasilnya integer. Semua retention kamu jadi 0%.

3. Lupa DISTINCT. Pelanggan yang belanja 5 kali sebulan kehitung 5 orang. Retention kamu bisa tembus 300%.

4. Nggak filter transaksi batal. Orang yang beli terus refund kehitung sebagai pelanggan yang bertahan.

5. Bandingin cohort yang umurnya beda. Cohort Mei belum punya data bulan-3. Sel kosong bukan berarti retention-nya 0. Bentuk segitiga itu wajar.

Referensi soal fungsi tanggal di PostgreSQL ada di dokumentasi resminya. Kalau CTE bertingkat masih bikin bingung, cek dulu glosarium CTE.

FAQ

Retention rate itu apa dan gimana rumusnya?

Retention rate adalah persentase pelanggan dari satu periode yang masih aktif di periode berikutnya. Rumusnya: jumlah pelanggan cohort yang aktif di bulan ke-N, dibagi ukuran cohort di bulan ke-0, dikali 100. Yang penting diinget, penyebutnya selalu ukuran cohort awal, bukan jumlah pelanggan bulan sebelumnya. Kalau penyebutnya salah, angkanya bisa kelihatan naik padahal pelanggannya berkurang.

Apa bedanya cohort retention sama repeat purchase rate?

Repeat purchase rate cuma ngitung berapa persen pelanggan yang pernah beli lebih dari sekali, tanpa peduli kapan. Cohort retention ngasih dimensi waktu: berapa persen yang masih balik di bulan ke-1, ke-2, ke-3. Cohort retention lebih berguna buat ngelacak apakah perubahan produk atau kampanye kamu beneran ngefek, soalnya kamu bisa bandingin cohort lama sama cohort baru.

Kenapa cohort table bentuknya segitiga?

Soalnya cohort yang lahir bulan Januari udah punya kesempatan bertahan 6 bulan, sementara cohort Juni baru punya data 1 bulan. Jadi baris paling atas panjang, baris paling bawah pendek. Bentuk segitiga itu normal dan justru penting: jangan bandingin angka bulan ke-3 dari cohort yang belum sampai bulan ke-3.

Retention rate berapa yang dianggap sehat?

Tergantung jenis bisnisnya. Buat e-commerce kebutuhan harian, retention bulan 1 di kisaran 25-35% udah lumayan. Buat barang tahan lama kayak elektronik, angka 5% pun wajar. Patokan yang lebih berguna daripada benchmark orang lain: bandingin cohort kamu bulan ini sama cohort tiga bulan lalu. Kalau kurvanya makin datar, kamu ke arah yang bener.

Query cohort ini jalan di MySQL?

Perlu sedikit penyesuaian. MySQL nggak punya DATE_TRUNC, jadi ganti pakai DATE_FORMAT dengan pola tahun-bulan. Buat hitung selisih bulan, MySQL punya TIMESTAMPDIFF yang malah lebih ringkas daripada versi PostgreSQL. Logika CTE-nya sendiri sama persis dan jalan di MySQL 8 ke atas.

Penutup

Yang perlu kamu inget:

  • Penyebutnya selalu ukuran cohort awal. Ini kesalahan paling mahal.
  • COUNT(DISTINCT pelanggan_id), bukan COUNT(*). Kita ngitung orang, bukan transaksi.
  • Kurva yang mendatar setelah bulan 2 itu tanda bagus. Yang bertahan segitu, nempel.

Copy query di atas, ganti nama tabel dan kolomnya sesuai database kamu, dan jalanin. Lima menit, dan kamu bakal tau apakah bisnis kamu beneran tumbuh atau cuma sibuk. Lanjut ke metrik harian data analyst e-commerce buat lihat retention duduk di mana dalam gambaran besarnya.

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