Ana içeriğe geç
Kesit SQL
Orta · İleri Sorgu Yapıları

Boşluk doldurma: son bilinen değerle ilerlemek

Eksik günleri takvimle tamamlamak ve boş kalan değeri bir önceki bilinen değerle doldurmak (forward fill): ilişkili alt sorgu, pencere ile grup numarası ve IGNORE NULLS.

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

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.

DikkatDizinin başında boşluk varsa (ilk gün hafta sonuysa) doldurulacak bir önceki değer yoktur; sorgu NULL döndürür. Takvimi bir gün geriden başlatmak ya da ilk değeri bilinçli olarak seçmek gerekir.
Alıştırmalara geç (7)