Önceki bölümde verileri filtrelemeyi öğrendik. Filtreleme yöntemiyle belli sayıda satır aralığını döndüren sorgular da yazabiliriz. Bu bölümde SELECT ifadesinde alınacak satırların sayısını belirlemek için TOP ifadesinin nasıl kullanılacağını öğreneceğiz. Ayrıca ORDER BY ifadesini OFFSET-FETCH ifadeleriyle birlikte kullanarak satırların nasıl sınırlandırılacağını da öğreneceğiz.

SELECT İfadesinde TOP İfadesi Kullanarak Filtreleme İşlemi

Bir sorgudan sonuç döndürülürken WHERE ile filtrelemenin yanısıra döndürülen toplam satır sayısını da sınırlandırmanız gerekebilir. SELECT ifadesinde Microsoft tarafından oluşturulan TOP ifadesini kullanarak sayıyla veya yüzde şeklinde döndürülecek satır sayısını belirleyebiliriz.

TOP seçeneğinin basitleştirilmiş syntax’ı aşağıdaki gibidir:

SELECT TOP (N) <column_list>
FROM <table_source>
WHERE <search_condition>
ORDER BY <order list>; 

Örneğin, Sales.Orders tablosundan en son beş siparişi görüntülemek için aşağıdaki sorguyu kullanabilirsiniz:

SELECT TOP (5) orderid, custid, orderdate
FROM Sales.Orders
ORDER BY orderdate DESC;

Not: TOP operatörü ORDER BY ifadesine bağlı olarak çalışmaktadır. Önceki örnekte, ORDER BY kaldırılırsa herhangi beş sipariş döndürülecektir.

TOP ifadesine ek olarak seçilen N tane satırda bulunabilecek değerlere sahip herhangi bir satırı alan WITH TIES seçeneğini de kabul etmektedir.

Mesela aşağıdaki sorgu en yeni sipariş tarihlerine sahip beş satır döndürür:

SELECT TOP (5) orderid, custid, orderdate
FROM Sales.Orders
ORDER BY orderdate DESC;

Dönen sonuç:

orderid custid orderdate
----------- ----------- -----------------------
11077 65 2008-05-06 00:00:00.000
11076 9 2008-05-06 00:00:00.000
11075 68 2008-05-06 00:00:00.000
11074 73 2008-05-06 00:00:00.000
11073 58 2008-05-05 00:00:00.000

Bununla birlikte, TOP ifadesine WITH TIES seçeneğini eklenince ikinci sipariş tarihi için daha fazla kaydın döndürüldüğünü göreceksiniz:

SELECT TOP (5) WITH TIES orderid, custid, orderdate
FROM Sales.Orders
ORDER BY orderdate DESC;

Sonuç:

orderid custid orderdate
----------- ----------- -----------------------
11077 65 2008-05-06 00:00:00.000
11076 9 2008-05-06 00:00:00.000
11075 68 2008-05-06 00:00:00.000
11074 73 2008-05-06 00:00:00.000
11073 58 2008-05-05 00:00:00.000
11072 20 2008-05-05 00:00:00.000
11071 46 2008-05-05 00:00:00.000
11070 44 2008-05-05 00:00:00.000
(8 row(s) affected)

Satır sayısının belirli bir yüzdesini döndürmek için TOP ile birlikte PERCENT seçeneğini kullanabilirsiniz.

Örneğin, Sales.Orders tablosu 830 sipariş kaydı içeriyorsa, aşağıdaki sorgu 83 kayıt döndürecektir:

SELECT TOP (10) PERCENT orderid, custid, orderdate
FROM Sales.Orders
ORDER BY orderdate DESC;

Not: Amaç satır sayımı olduğundan TOP (N) PERCENT en yakın tam sayıya yuvarlanır.

ORDER BY ile OFFSET-FETCH Kullanarak Filtreleme İşlemleri

TOP ifadesi, birçok SQL Server uzmanı tarafından yalnızca belirli bir satır aralığını elde etmek için kullanılan bir yöntem olsa da belli başlı dezavantajları da vardır:

  • T-SQL ve SQL Server’a özeldir.
  • Bir satır aralığının atlanmasını desteklemez.
  • ORDER BY deyimine bağlı olduğundan, TOP tarafından filtrelenen satırlar için bir sıralama düzeni belirtemezsiniz.

Bu kısıtlamaların bir kısmını gidermek için Microsoft tarafından ORDER BY ifadesine OFFSET-FETCH ifadeleri eklenmiştir.

TOP ifadesi gibi OFFSET-FETCH de yalnızca sorgu tarafından seçilen satır aralığının döndürülmesini sağlar. Ancak bir başlangıç noktası (offset) sağlama işlevi ve kaç satır döndürmek istediğinizi belirten bir değer belirtmeniz gerekir. Böylece sonuçların numaralandırılması uygun bir teknikle gerçekleştirilmiş olur.

Numaralandırma yaparken, OFFSET-FETCH deyimini kullanılan her bir sorgunun önceki veya sonraki sorgudan bağımsız olarak çalıştığını dikkate almanız gerekir. İşlemler sunucu tarafında değil client tarafında gerçekleşmektedir.

Bir sonraki bölümde de göreceğimiz üzer, OFFSET-FETCH kullanımı daha doğal İngilizce syntax’i sağlayacak şekilde yazılmıştır.

OFFSET-FETCH ifadesi, SQL Server 2012, 2014, 2016, 2017 ve 2019 sürümlerinde desteklenmektedir.

OFFSET-FETCH Syntax

OFFSET-FETCH syntax’ı aşağıdaki gibidir:

OFFSET { integer_constant | offset_row_count_expression } { ROW | ROWS }  
[  
  FETCH { FIRST | NEXT } {integer_constant | fetch_row_count_expression } { ROW | ROWS } ONLY  
] 

OFFSET-FETCH ifadelerini kullanabilmek için, aşağıdaki örnekte olduğu gibi bir başlangıç OFFSET değeri (sıfır olabilir) ve isteğe bağlı sayıda döndürülecek satır sayısı belirtmeniz gereklidir.

Bu örnekte ilk 10 satır atlanacak ve ardından sipariş tarihine göre sonraki 10 satırı döndürecektir:

SELECT orderid, custid, orderdate
FROM Sales.Orders
ORDER BY orderdate, orderid DESC
OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;

Syntax tanımında görüldüğü üzere OFFSET ifadesi kullanımı zorunlu ancak FETCH zorunlu değildir. FETCH ifadesi çıkarılırsa, OFFSET’i izleyen tüm satırlar döndürülür. Ayrıca, ROW ve ROWS ifadelerinin, daha doğal bir syntax sağlayan FIRST ve NEXT ifadeleriyle değiştirilebilir olduğunu göreceğiz.

Sonuçların doğruluğunu teyit amacıyla, özellikle sayfadan veri sayfasına geçildiğinde, benzersiz değerlerin olduğu bir belirleyici sonuç döndürecek ORDER BY ifadesi oluşturmak da önemlidir. Her ne kadar muhtemel gözükmese de, SQL Server’ın query optimizer’ı nedeniyle, satır aralığı belirleyici olmadığı sürece bir satırın birden fazla sayfada görünmesi teknik olarak mümkündür.

Not: Paging amacıyla OFFSET-FETCH kullanmak için, satır sayımı ifadelerine ek olarak OFFSET değerini bir değişken veya parametre olarak verebilirsiniz. Sonraki bölümlerde değişkenler ve Stored Procedure parametreleri hakkında daha fazla bilgi edineceksiniz.

Aşağıda T-SQL sorgularında OFFSET-FETCH kullanmanın bazı örnekleri verilmiştir. Bu sorguların hepsi AdventureWorks veritabanını kullanmaktadır.

Sipariş tarihine göre belirlenen ilk 50 satırı almak için sıfır offsetle başlanmıştır. SELECT TOP (50) sorgusuna benzer bir sonuç döndürmektedir:

SELECT orderid, custid, empid, orderdate
FROM Sales.Orders
ORDER BY orderdate DESC
OFFSET 0 ROWS FETCH FIRST 50 ROWS ONLY;

Bu sorguda ise bir sonuç kümesinin 51-100 arasındaki satırlar alınmaktadır:

SELECT orderid, custid, empid, orderdate
FROM Sales.Orders
ORDER BY orderdate DESC
OFFSET 50 ROWS FETCH NEXT 50 ROWS ONLY;

Not: OFFSET-FETCH ifadesi, SQL Server 2008 R2 ve daha önceki sürümlerde desteklenmemektedir.

Kaynak :
TOP (Transact-SQL)
ORDER BY Clause (Transact-SQL)