Ana içeriğe geç
Kesit SQL
Orta · Pencere Fonksiyonları

FIRST_VALUE, LAST_VALUE, NTH_VALUE ve varsayılan çerçeve tuzağı

Bölümdeki ilk/son/n. değere erişim ve ROWS BETWEEN ... UNBOUNDED FOLLOWING.

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ç.

Bölümün ilk değeri

SELECT category, name, price,
       FIRST_VALUE(name) OVER (PARTITION BY category ORDER BY price) AS en_ucuz
FROM products
WHERE category IN ('Kitap', 'Hediye');

LAST_VALUE neden yanlış görünür?

ORDER BY içeren bir pencerenin varsayılan çerçevesi “bölümün başından bu satıra kadar”dır (RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW). Bu yüzden LAST_VALUE çoğu zaman satırın kendisini döndürür. Bölümün gerçek son değeri için çerçeveyi açıkça genişlet:

SELECT category, name, price,
       LAST_VALUE(name) OVER (PARTITION BY category ORDER BY price) AS yanlis_son,
       LAST_VALUE(name) OVER (PARTITION BY category ORDER BY price
                              ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS dogru_son
FROM products
WHERE category = 'Kitap';
Pratik çözümSon değeri, sıralamayı ters çevirip FIRST_VALUE ile almak çerçeve derdinden kurtarır: FIRST_VALUE(name) OVER (PARTITION BY category ORDER BY price DESC).

NTH_VALUE

SELECT DISTINCT category,
       NTH_VALUE(name, 2) OVER (PARTITION BY category ORDER BY price DESC
                                ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS ikinci_pahali
FROM products;

NTH_VALUE; SQL Server'da (2022 dahil) yoktur, orada ROW_NUMBER ile n. satır seçilir.

Derinleş: son değeri güvenle almak

Üç yol aynı sonucu verir: sıralamayı tersine çevirip FIRST_VALUE, çerçeveyi genişletip LAST_VALUE ya da ROW_NUMBER ile filtre. En okunur ve hatasız olanı genellikle ilkidir.

SELECT DISTINCT restaurant_id,
       FIRST_VALUE(name) OVER (PARTITION BY restaurant_id ORDER BY price DESC, name) AS en_pahali
FROM lk_menu_items
WHERE restaurant_id <= 3;
Alıştırmalara geç (6)