Ana içeriğe geç
Kesit SQL
Orta · Veri Analisti

İş metrikleri: ciro, sipariş, ortalama sepet

KPI tanımlamak ve tek sorguda KPI tablosu üretmek.

Uygulamada aç, 5 alıştırmayı çözÜcretsiz, hesap gerekmez, kurulum yok.

Bu sayfa dersin okuma sürümüdür. Metin bir kutuyu çalıştırmanı ya da adıma geçmeni söylüyorsa dersi uygulamada aç.

Metrik tanımı her şeydir

“Ciro ne kadar?” sorusunun cevabı tanıma göre değişir: İptaller dahil mi? İndirim düşülmüş mü? İadeler? Bir analistin ilk işi metriği yazılı ve tek bir tanıma bağlamaktır. Bu kursta:

Aylık KPI tablosu

SELECT strftime('%Y-%m', o.order_date) AS ay,
       COUNT(DISTINCT o.order_id) AS siparis,
       COUNT(DISTINCT o.customer_id) AS aktif_musteri,
       ROUND(SUM(oi.quantity * oi.unit_price * (1 - oi.discount)), 0) AS net_ciro,
       ROUND(SUM(oi.quantity * oi.unit_price * (1 - oi.discount)) / COUNT(DISTINCT o.order_id), 1) AS aov
FROM orders o
JOIN order_items oi ON oi.order_id = o.order_id
WHERE o.status = 'delivered' AND o.order_date >= '2024-01-01'
GROUP BY ay
ORDER BY ay;
Kontrol toplamıHer KPI sorgusunu bilinen bir rakamla (finans raporu, önceki dashboard) karşılaştır. Farklıysa önce tanımı, sonra JOIN grain düzeyini kontrol et.

Derinleş: KPI ağacı ve grain hataları

Tek bir ciro rakamı “ne oldu?” sorusunu cevaplar, “neden?” sorusunu cevaplamaz. Bu yüzden analistler ciroyu çarpanlarına ayırır:

Net ciro = aktif müşteri × müşteri başına sipariş (frekans) × ortalama sepet (AOV)

Üç çarpandan hangisinin değiştiğini görmek aksiyonu belirler. Müşteri sayısı düştüyse sorun edinmededir, frekans düştüyse elde tutmada, AOV düştüyse fiyat ya da sepet büyüklüğündedir. Anadolu Market'te teslim edilmiş siparişlerde 2023'ten 2024'e ciro 335.573 TL'den 636.316 TL'ye çıktı. Aktif müşteri 74'ten 120'ye (%62), frekans 3,23'ten 3,51'e, AOV 1.404'ten 1.511 TL'ye yükseldi. Yani büyümenin büyük kısmı yeni müşteriden geliyor. Bu cümleyi tek bir ciro sayısından kuramazdın.

En sık hata: JOIN sonrası grain

orders tablosunu order_items ile birleştirdiğinde her satır artık bir sipariş kalemi olur. Bu satırlarda COUNT(*) sipariş sayısını değil kalem sayısını verir. AVG(tutar) da sepet ortalamasını değil kalem ortalamasını verir:

SELECT COUNT(*) AS satir,
       COUNT(DISTINCT o.order_id) AS siparis,
       ROUND(AVG(oi.quantity * oi.unit_price * (1 - oi.discount)), 1) AS kalem_ort,
       ROUND(SUM(oi.quantity * oi.unit_price * (1 - oi.discount)) / COUNT(DISTINCT o.order_id), 1) AS aov
FROM orders o
JOIN order_items oi ON oi.order_id = o.order_id
WHERE o.status = 'delivered'
  AND o.order_date >= '2024-01-01' AND o.order_date < '2025-01-01';

2024'te 421 sipariş 759 kaleme yayılıyor. “Ortalama sepet” diye 838 TL raporlamak, gerçek AOV'yi (1.511 TL) neredeyse yarıya indirir.

HataBelirtiDoğrusu
JOIN sonrası COUNT(*)Sipariş sayısı şişerCOUNT(DISTINCT order_id)
Kalem ortalamasıAOV düşük çıkarToplam ciro ÷ tekil sipariş
Payda kaymasıİptal oranı %8,2 mi, %10,5 mi?Payda tüm siparişler; teslim edilenler değil
Oranların ortalamasıKüçük gruplar fazla ağırlık alırÖnce pay ve paydayı topla, sonra böl
Mini kontrol listesi1) Metriğin tanımı yazılı mı? 2) Sorgunun her satırı neyi temsil ediyor (sipariş mi, kalem mi)? 3) Payda “bu olayı yaşayabilecek herkes” mi? 4) Sonucu bilinen bir toplamla karşılaştırdın mı?
Alıştırmalara geç (5)