Sorun
Ilgaz Bank'ın döviz kuru tablosu (bank_fx) yalnızca iş günlerini içerir. Hafta sonu yapılan bir döviz işleminin TL karşılığını hesaplamak için o günün kuru gerekir; finans ekiplerinin kuralı: hafta sonu ve tatilde son bilinen kur geçerlidir. Buna “son bilinen değerle doldurma” (forward fill, LOCF) denir.
Adım 1: takvimi tamamla
WITH RECURSIVE t(gun) AS ( SELECT '2024-03-01' UNION ALL SELECT date(gun, '+1 day') FROM t WHERE gun < '2024-03-14' ) SELECT t.gun, f.try_rate FROM t LEFT JOIN bank_fx f ON f.rate_date = t.gun AND f.currency = 'USD' ORDER BY t.gun;
Hafta sonları try_rate boş gelir.
Yol 1: ilişkili alt sorgu
Her gün için o güne kadarki en son kur tarihini bul, sonra o tarihin kurunu al. Her SQL türünde çalışır, anlaşılması kolaydır; büyük tablolarda yavaş olabilir.
WITH RECURSIVE t(gun) AS (
SELECT '2024-03-01' UNION ALL SELECT date(gun, '+1 day') FROM t WHERE gun < '2024-03-14'
)
SELECT t.gun,
(SELECT f.try_rate FROM bank_fx f
WHERE f.currency = 'USD' AND f.rate_date <= t.gun
ORDER BY f.rate_date DESC LIMIT 1) AS kur
FROM t
ORDER BY t.gun;
Yol 2: pencere ile grup numarası
Dolu değerleri kümülatif say: her dolu değer yeni bir grup başlatır, ardından gelen boş satırlar aynı grupta kalır. Sonra grup içindeki tek dolu değeri al.
WITH RECURSIVE t(gun) AS (
SELECT '2024-03-01' UNION ALL SELECT date(gun, '+1 day') FROM t WHERE gun < '2024-03-14'
),
k AS (
SELECT t.gun, f.try_rate,
COUNT(f.try_rate) OVER (ORDER BY t.gun ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS grp
FROM t LEFT JOIN bank_fx f ON f.rate_date = t.gun AND f.currency = 'USD'
)
SELECT gun, MAX(try_rate) OVER (PARTITION BY grp) AS kur
FROM k
ORDER BY gun;
COUNT(sütun) boşları saymadığı için grup numarası yalnızca dolu satırlarda artar. Bu yöntem tabloyu bir kez tarar ve her SQL türünde çalışır.
Yol 3: IGNORE NULLS
Oracle, BigQuery, Snowflake ve SQL Server 2022 şu kısa yazımı destekler: LAST_VALUE(try_rate IGNORE NULLS) OVER (ORDER BY gun). PostgreSQL ve MySQL'de yoktur; orada 2. yol kullanılır.