TOP
SQL Server'da ilk N satır TOP ile alınır. TOP, SELECT'ten (ve varsa DISTINCT'ten) hemen sonra yazılır. Sıralama olmadan TOP rastgele N satır döndürür; her zaman ORDER BY ile kullan.
SELECT TOP 5 name, price FROM products ORDER BY price DESC;
WITH TIES: son sıradaki eşitleri de getir
En yüksek maaşlı 10 çalışanı istiyoruz ama 10. sıradaki maaşı alan başka biri de varsa onu dışarıda bırakmak haksızlık olur:
SELECT TOP 10 WITH TIES first_name, salary FROM employees ORDER BY salary DESC;
Sonuç 10 değil 11 satırdır; çünkü 10. ve 11. sıradaki çalışanların maaşı aynı.
TOP PERCENT
SELECT TOP 10 PERCENT name, price FROM products ORDER BY price DESC;
OFFSET-FETCH ile sayfalama
Web sayfalarında “2. sayfa” gibi gösterimler için standart SQL'in OFFSET-FETCH yazımı kullanılır (SQL Server 2012+). ORDER BY zorunludur.
DECLARE @sayfa INT = 2, @boyut INT = 5; SELECT name, price FROM products ORDER BY price DESC OFFSET (@sayfa - 1) * @boyut ROWS FETCH NEXT @boyut ROWS ONLY;
DELETE TOP (1000) FROM log WHERE ... gibi büyük silmeleri parçalara bölmek için de kullanılır.Derinleş: TOP'u doğru kullanmak ve sayfalama
TOP basit görünür ama üç inceliği vardır: belirlilik, değişkenle kullanım ve büyük tablolarda sayfalama.
Belirlilik
ORDER BY olmadan TOP “ilk N”i değil, motorun o an en kolay bulduğu N satırı verir; aynı sorgu yarın farklı satırlar döndürebilir. ORDER BY sütunu benzersiz değilse aynı sorun eşitliklerde yaşanır. Ya eşitlik bozucu ekle (ORDER BY commission_pct DESC, restaurant_id) ya da eşitleri bilerek dahil et (WITH TIES).
Değişkenle TOP
Satır sayısı değişkenden geliyorsa parantez zorunludur: TOP (@n). Lezzet Kurye'de en yüksek komisyonlu 3 restoranı isteyelim:
DECLARE @n INT = 3; SELECT TOP (@n) WITH TIES name, commission_pct FROM lk_restaurants ORDER BY commission_pct DESC;
Sonuç 3 değil 5 satırdır: beş restoranın komisyonu %22. “İlk 3” istenirken 5 satır gelmesi iş açısından doğru olabilir (ödül listesi) ya da yanlış (3 kişilik kontenjan); karar sorunun sahibine aittir.
OFFSET-FETCH'in gizli maliyeti ve keyset sayfalama
OFFSET 100000 ROWS FETCH NEXT 20 ROWS ONLY yazdığında motor 100.020 satırı sıralayıp ilk 100.000'ini atar; sayfa numarası büyüdükçe sorgu yavaşlar. Ayrıca iki sayfa isteği arasında yeni satır eklenirse kayıtlar kayar (aynı satır iki sayfada görünür). Keyset (seek) sayfalamada önceki sayfanın son anahtarı hatırlanır ve indeks doğrudan oradan okunur:
DECLARE @son_id INT = 40; -- önceki sayfanın son customer_id değeri SELECT TOP 5 customer_id, first_name, city FROM customers WHERE customer_id > @son_id ORDER BY customer_id;
| Yöntem | Artı | Eksi |
|---|---|---|
| OFFSET-FETCH | “5. sayfaya git” kolay | Derin sayfalarda yavaş, kayma olur |
| Keyset | Her sayfa aynı hızda, kayma yok | Rastgele sayfaya atlanamaz, sıralama anahtarı benzersiz olmalı |
| ROW_NUMBER + filtre | Taşınabilir | OFFSET gibi tüm önceki satırları işler |
LIMIT n OFFSET m; Oracle 12c+ ve PostgreSQL 13+ FETCH FIRST n ROWS WITH TIES; MySQL ve SQLite'ta WITH TIES yoktur, RANK() <= n ile yazılır.