Soru
Görüşmeci“Her ay için teslim edilen ciroyu, bir önceki aya göre büyümeyi ve yılbaşından bu yana kümülatif ciroyu getir.” Takip: “Her gün için son 7 günün cirosu nedir? Sipariş olmayan günler de görünmeli.”
Önce netleştir
Kod yazmadan önce sorulacak sorular. Her biri farklı bir sorguya götürür; sormamak en sık puan kaybıdır.
- Ciro tanımı: net mi (indirim düşülmüş), hangi durumlar dahil?
- Kümülatif toplam her yıl sıfırlansın mı?
- “Son 7 gün” bugünü içeriyor mu?
- Sipariş olmayan ay/gün 0 olarak görünmeli mi?
Yaklaşım
- Önce aylık (ya da günlük) toplam tablosunu kur.
- LAG ile bir önceki dönemi getir, farkı yüzdeye çevir.
- SUM OVER (PARTITION BY yıl ORDER BY ay) ile yılbaşından bu yana kümülatif.
- Boş günler için önce takvim üret, sonra LEFT JOIN; çerçeveyi ROWS BETWEEN 6 PRECEDING AND CURRENT ROW yap.
Çözüm 1: aylık tablo + LAG + kümülatif
WITH a AS (
SELECT strftime('%Y', o.order_date) AS yil, strftime('%Y-%m', o.order_date) AS ay,
SUM(oi.quantity * oi.unit_price * (1 - oi.discount)) AS ciro
FROM orders o JOIN order_items oi ON oi.order_id = o.order_id
WHERE o.status = 'delivered'
GROUP BY strftime('%Y', o.order_date), strftime('%Y-%m', o.order_date)
)
SELECT ay, ROUND(ciro) AS ciro,
ROUND(100.0 * (ciro - LAG(ciro) OVER (ORDER BY ay)) / LAG(ciro) OVER (ORDER BY ay), 1) AS buyume,
ROUND(SUM(ciro) OVER (PARTITION BY yil ORDER BY ay ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)) AS ytd
FROM a
WHERE ay >= '2024-01'
ORDER BY ay;
Çözüm 2: takvim + LEFT JOIN + hareketli pencere
WITH RECURSIVE takvim(gun) AS (
SELECT '2024-12-01' UNION ALL SELECT date(gun, '+1 day') FROM takvim WHERE gun < '2024-12-31'
),
g AS (
SELECT o.order_date AS gun, SUM(oi.quantity * oi.unit_price * (1 - oi.discount)) AS ciro
FROM orders o JOIN order_items oi ON oi.order_id = o.order_id
WHERE o.status = 'delivered' AND o.order_date >= '2024-11-25'
GROUP BY o.order_date
)
SELECT t.gun, ROUND(COALESCE(g.ciro, 0)) AS ciro,
ROUND(SUM(COALESCE(g.ciro, 0)) OVER (ORDER BY t.gun ROWS BETWEEN 6 PRECEDING AND CURRENT ROW)) AS son7
FROM takvim t LEFT JOIN g ON g.gun = t.gun
ORDER BY t.gun;
İkinci çözümdeki takvim adımı çok önemlidir: boş günler tabloda olmazsa “6 PRECEDING” altı satır öncesine, yani belki on gün öncesine bakar. Ayrıca ilk 6 gün eksik pencereyle hesaplanır; bunu görüşmeciye söylemek ya da takvimi 6 gün geriden başlatmak gerekir.
Sınır durumları
| Durum | Ne olur? |
|---|---|
| Önceki dönem yok | LAG NULL döner; büyüme NULL kalmalı, 0 değil |
| Önceki dönem 0 | Sıfıra bölme: NULLIF(LAG(...), 0) |
| Boş günler | Takvim olmadan pencere yanlış genişler |
| Varsayılan çerçeve | ORDER BY olan SUM OVER varsayılanı RANGE'dir; aynı tarihli satırlar birlikte toplanır |
Takip soruları
- Geçen yılın aynı ayıyla (YoY) nasıl karşılaştırırsın? (LAG(ciro, 12) ya da yıl − 1 ile self join)
- Ay içinde bugüne kadar (MTD) ciro nasıl hesaplanır?
- Bu sorguyu bir BI aracına verecek olsan hangi taneciği seçerdin?
Görüşmeci neye bakıyor?Boş dönemleri ve pencere çerçevesini kendiliğinden düşünmen; büyümede NULL ile 0 farkını gözetmen.