Soru
Pazarlama direktörü soruyor: “2023'te ilk siparişini veren müşterilerin kaçta kaçı sonraki aylarda geri geldi? Hangi ayın müşterileri daha sadık?” Cevap bir kohort matrisi: her satır bir başlangıç ayı, her sütun “kaç ay sonra” sorusu.
Sorgu
SELECT * FROM adim_adi LIMIT 20;WITH ilk AS ( -- 1) Müşterinin kohortu: ilk sipariş ayı
SELECT customer_id, MIN((CAST(strftime('%Y', order_date) AS INTEGER) * 12 + CAST(strftime('%m', order_date) AS INTEGER))) AS kohort_no
FROM orders
GROUP BY customer_id
),
aktif AS ( -- 2) Müşterinin sipariş verdiği her ay (tekrarsız)
SELECT DISTINCT customer_id, (CAST(strftime('%Y', order_date) AS INTEGER) * 12 + CAST(strftime('%m', order_date) AS INTEGER)) AS ay_no
FROM orders
),
fark AS ( -- 3) Kohorttan bu yana geçen ay sayısı
SELECT i.kohort_no, a.ay_no - i.kohort_no AS ay_farki, a.customer_id
FROM aktif a
JOIN ilk i ON i.customer_id = a.customer_id
),
boyut AS ( -- 4) Her kohortun büyüklüğü
SELECT kohort_no, COUNT(*) AS musteri
FROM ilk
GROUP BY kohort_no
)
SELECT -- 5) Matris: kohort satırda, ay farkı sütunda
FLOOR((b.kohort_no - 1) / 12) AS yil,
(b.kohort_no - 1) % 12 + 1 AS ay,
b.musteri,
ROUND(100.0 * COUNT(DISTINCT CASE WHEN f.ay_farki = 1 THEN f.customer_id END) / b.musteri, 1) AS m1,
ROUND(100.0 * COUNT(DISTINCT CASE WHEN f.ay_farki = 2 THEN f.customer_id END) / b.musteri, 1) AS m2,
ROUND(100.0 * COUNT(DISTINCT CASE WHEN f.ay_farki = 3 THEN f.customer_id END) / b.musteri, 1) AS m3,
ROUND(100.0 * COUNT(DISTINCT CASE WHEN f.ay_farki BETWEEN 1 AND 6 THEN f.customer_id END) / b.musteri, 1) AS ilk6ay
FROM boyut b
JOIN fark f ON f.kohort_no = b.kohort_no
WHERE b.kohort_no >= 2023 * 12 + 1 AND b.kohort_no <= 2023 * 12 + 12
GROUP BY b.kohort_no, b.musteri
ORDER BY b.kohort_no;
Adım adım
| Adım | Ne yapar? | Çıktının bir satırı |
|---|---|---|
ilk | Müşterinin ilk sipariş ayını “ay numarası” (yıl × 12 + ay) olarak bulur | müşteri 17 → 24282 (2023 Haziran) |
aktif | Müşterinin sipariş verdiği her ayı bir kez listeler | müşteri 17 → 24282, 24284, 24290 |
fark | Her aktif ay için kohorttan bu yana geçen ay sayısı | 24284 − 24282 = 2 |
boyut | Kohort başına müşteri sayısı (oranların paydası) | 24282 → 9 müşteri |
son SELECT | Koşullu sayımla matrisi kurar, oranı kohort büyüklüğüne böler | 2023, 6, 9, m1, m2, m3, ilk6ay |
Neden ay numarası?
İki tarih arasındaki “ay farkı” SQL türüne göre farklı hesaplanır (SQL Server DATEDIFF(month) ay sınırlarını sayar, PostgreSQL AGE gün hassasiyetinde çalışır). Yıl × 12 + ay dönüşümü her SQL türünde aynı sonucu verir ve aritmetiği basitleştirir. Geri dönüşüm: yıl = FLOOR((no − 1) / 12), ay = (no − 1) % 12 + 1. FLOOR gerekir; çünkü MySQL, Oracle ve BigQuery tam sayıları da ondalıklı böler.
Sık hatalar
- Aynı ayda iki sipariş:
aktifadımında DISTINCT olmazsa müşteri aynı ay için iki kez sayılır; COUNT(DISTINCT) son adımda bunu kurtarır ama ara adımlar şişer. - Payda: Oran, o ay aktif olanların sayısına değil kohortun başlangıç büyüklüğüne bölünür.
- Sağdan kesilme: 2024 Aralık kohortunun M3 değeri henüz oluşmamıştır. Bu yüzden sorgu 2023 kohortlarıyla sınırlı.