Sipariş olmayan gün raporda kaybolur
Günlük sipariş sayısını GROUP BY order_date ile alırsan, hiç sipariş olmayan günler sonuçta hiç görünmez. Grafikte bu günler atlanır ve trend olduğundan iyi görünür. Çözüm: önce eksiksiz bir gün listesi üret, sonra veriyi ona LEFT JOIN ile bağla.
1. Özyinelemeli CTE ile gün listesi (her SQL türünde)
WITH RECURSIVE gunler(gun) AS (
SELECT DATE('2024-12-01')
UNION ALL
SELECT DATE(gun, '+1 day') FROM gunler WHERE gun < '2024-12-31'
)
SELECT g.gun,
COUNT(o.order_id) AS siparis
FROM gunler g
LEFT JOIN orders o ON o.order_date = g.gun
GROUP BY g.gun
ORDER BY g.gun;
OPTION (MAXRECURSION 0) eklemelisin.2. Hazır seri fonksiyonları
SQL Server 2022 ve PostgreSQL seri üreten fonksiyonlara sahiptir; Oracle'da klasik yöntem CONNECT BY LEVEL'dır:
SELECT DATEADD(day, value, '2024-12-01') AS gun FROM GENERATE_SERIES(0, 6);
-- Oracle SELECT DATE '2024-12-01' + LEVEL - 1 AS gun FROM dual CONNECT BY LEVEL <= 7;
Takvim (tarih boyutu) tablosu
Raporlama yapılan her veritabanında genellikle kalıcı bir takvim tablosu bulunur: her gün için bir satır ve hazır hesaplanmış sütunlar. Böylece “hafta sonu mu?”, “hangi çeyrek?”, “resmî tatil mi?” soruları her sorguda yeniden hesaplanmaz.
WITH RECURSIVE gunler(gun) AS (
SELECT DATE('2024-12-01')
UNION ALL
SELECT DATE(gun, '+1 day') FROM gunler WHERE gun < '2024-12-31'
)
SELECT gun,
CAST(strftime('%Y', gun) AS INTEGER) AS yil,
CAST(strftime('%m', gun) AS INTEGER) AS ay,
CAST(strftime('%w', gun) AS INTEGER) AS haftanin_gunu,
CASE WHEN CAST(strftime('%w', gun) AS INTEGER) IN (0, 6) THEN 1 ELSE 0 END AS hafta_sonu
FROM gunler;