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

Dashboard için sorgu tasarımı

Tarih iskeleti, sıfır doldurma ve BI aracına hazır tablolar.

Uygulamada aç, 6 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ç.

Grafikte boşluk olmasın

Bir günde hiç sipariş yoksa GROUP BY o günü hiç döndürmez ve çizgi grafik yanlış görünür. Çözüm: tarih iskeleti (date spine) üret, LEFT JOIN yap, NULL'ları 0 yap.

WITH RECURSIVE gun(d) AS (
  SELECT '2024-12-01' UNION ALL SELECT date(d, '+1 day') FROM gun WHERE d < '2024-12-31'
),
satis AS (
  SELECT order_date, COUNT(*) AS siparis FROM orders GROUP BY order_date
)
SELECT g.d AS tarih, COALESCE(s.siparis, 0) AS siparis
FROM gun g LEFT JOIN satis s ON s.order_date = g.d
ORDER BY g.d;

BI aracına hazır tablo ilkeleri

Oranların ortalaması tuzağıGünlük dönüşüm oranlarının ortalaması, dönemin dönüşüm oranı değildir. Doğrusu: SUM(donusen) / SUM(ziyaret).

Derinleş: Dönem karşılaştırması, kümülatif ve hareketli ortalama

Yönetici bir dashboard'a baktığında hep aynı üç soruyu sorar: “Geçen yıla göre nasılız?”, “Yıl başından beri neredeyiz?”, “Gidişat ne yönde?”. Bunların SQL karşılıkları sırasıyla yıllık karşılaştırma (YoY), kümülatif toplam (YTD) ve hareketli ortalamadır.

Yıl içi kümülatif

WITH a AS (
  SELECT 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'
    AND o.order_date >= '2024-01-01' AND o.order_date < '2025-01-01'
  GROUP BY strftime('%Y-%m', o.order_date)
)
SELECT ay, ROUND(ciro) AS ciro,
       ROUND(SUM(ciro) OVER (ORDER BY ay ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)) AS ytd
FROM a
ORDER BY ay;

Yıllık karşılaştırmada üç tuzak

Hareketli ortalama

Günlük sipariş sayısı gürültülüdür; 7 günlük hareketli ortalama haftanın günü etkisini düzler. ROWS BETWEEN 6 PRECEDING AND CURRENT ROW “son 7 satır” demektir, “son 7 gün” değil. Sipariş olmayan günler tabloda yoksa pencere 7 günden daha geriye uzanır. Bu yüzden hareketli ortalamayı her zaman tarih iskeletinin üzerinde hesapla. Pencerenin ilk 6 gününde de 7'den az değer vardır. Raporda bu “ısınma” dönemini ya göstermez ya da önceki ayın verisini pencereye katarsın.

SoruKalıpDikkat
Geçen yıla göre?Kendine JOIN (yıl − 1, aynı ay)Küçük taban, yarım dönem
Yıl başından beri?SUM() OVER (ORDER BY ay)Yıl değişince PARTITION BY yil
Gidişat?AVG() OVER (ROWS 6 PRECEDING)Önce tarih iskeleti
Alıştırmalara geç (6)