Konuyu Oyla:
  • Derecelendirme: 5/5 - 1 oy
  • 1
  • 2
  • 3
  • 4
  • 5
SQL Server : MySQL : Sayfalama, Pagination
#1
Merhaba, bu yazıda yeni başlayanlar ve unutanlar için (bu gruba ben de dahilim Smile ) verilerin sayfalanmasını yani Pagination tekniğini fazla detaya inmeden, basite indirgenmiş bir şekilde anlatmaya çalışacağım. Daha da karmaşık hale getirmemek için performans konusuna değinmeyeceğim.

Pagination / Sayfalama neredeyse her yerde karşılaşabildiğimiz gerek masaüstü, gerek mobil, gerekse web projelerinde sıklıkla kullanılan, listelenecek olan verilerin kullanıcıya parçalar halinde "çağırılmasına" hizmet eden bir tekniktir.

Pagination'daki temel amaç listelenecek olan verilerin satır sayısını sınırlandırılması esasına dayanır, yani siz verilerin tamamını değil, belli bir aralıktakileri listelersiniz.

Bunu yapabilmek için SQL Server'da iki seçeneğimiz var, duruma ve performans maliyetine göre hangisini kullanacağınız size kalmıştır. Bunlar TOP ve OFFSET & FETCH ikilisidir.

Hem TOP, hem de OFFSET & FETCH deyimleri listelenecek olan satır sayısını sınırlandırmak için kullanılabilir fakat kullanım şekilleri hangi yöntemin sizin için en iyisi olduğunu etkileyecek düzeyde birbirinden farklılıklar arzeder.

TOP ile OFFSET & FETCH arasındaki fark nedir?

TOP Deyimi

TOP, bir sorgu sonuç kümesinin (sıralamaya göre) en tepesinden (listenin başından itibaren),  belirtilen sayı kadar satırı elde etmenizi sağlar. Örnekleme açısından aşağıdaki kodu inceleyebilirsiniz;

SELECT TOP 10
        Ad
      , Soyad
      , Eposta
FROM     dbo.Kisiler

Yukarıdaki kod, dbo.Kisiler tablosunda karşımıza çıkan ilk 10 satırı bize getirir. Her ne kadar ORDER BY, TOP kullanımı için gerekli değilmiş gibi gözükse de kullanılmasını tavsiye ederim. Sorgunun sonuna ORDER BY komutunu da eklersek listelenecek olan ilk 10 kayıt bizim belirttiğimiz sıralamaya uygun bir şekilde listelenecektir. Böylece beklenmedik verilerle karşılaşma riskinden de kurtulmuş oluruz.

SELECT TOP 10
        Ad
      , Soyad
      , Eposta
FROM     dbo.Kisiler
ORDER BY Soyad DESC

gibi...

TOP deyimini kullanırken istenen satır sayısını bir yüzde değeri olarak da belirtebiliriz. Diyelim ki 7305 adet satırı olan bir tablonuz var ve bu satırların sadece Yüzde 10'u ile ilgileniyorsunuz diyelim, bu durumda (7305 / 100) * 10 = 74 (yukarı yuvarlayacak şekilde) satır listelenecektir. Kullanımı ise şu şekilde;

SELECT TOP 10 PERCENT
        Ad
      , Soyad
      , Eposta
FROM     dbo.Kisiler
ORDER BY Soyad DESC 

Sonuç kümesinin başından itibaren belli miktarda veri çekilmesine hizmet ettiği için çoğu durumda TOP deyimi performans açısından faydalıdır. Fakat "PERCENT" ifadesi için aynı şeyi söyleyemeyiz. Percent deyiminin kullanılması söz konusu olduğunda SQL Server arka tarafta fazladan bir kaç iş daha yapar ve bu da performansı biraz etkiler. O nedenle PERCENT deyimini performans açısından pek önermem.

OFFSET ve FETCH Deyimleri

Bu iki deyim sonuç kümesinde belli bir "aralığı" elde etmek için kullanılır. OFFSET sonuç kümesinden kaç adet satırın "es geçileceğini", FETCH ise es geçilen satırlardan sonra kaç adet satır listeleneceğini belirtir.

ANSI ile uyumlu olan bu deyimler sanırım SQL Server 2012 ile birlikte sosyetenin cemiyet hayatına katıldılar Smile

OFFSET'i, FETCH deyimi olmadan kullanabilirsiniz fakat FETCH tek başına kullanılamaz. Tüm bunlarla birlikte OFFSET ve FETCH aslında "ORDER BY" deyimini genişleten iki "ek" ifadedir.

Örnek olması açısından aşağıdaki kodu inceleyelim; Bu örnekte ilk 10 kayıt es geçilecek, hemen peşi sıra, devamında gelen 10 kayıt ise listelenecektir.

SELECT   Ad
      , Soyad
      , Eposta
FROM     dbo.DENEYSEL_TABLO
ORDER BY Ad, Soyad
OFFSET 10 ROWS
FETCH NEXT 10 ROWS ONLY

Aşağıdaki örnek kullanım ise "TOP 10" ifadesiyle belirtilen kullanım ile aynı sonucu üretir;

SELECT   Ad
      , Soyad
      , Eposta
FROM     dbo.DENEYSEL_TABLO
ORDER BY Ad, Soyad
OFFSET 0 ROWS    --> "0" ibaresine dikkat edin !
FETCH NEXT 10 ROWS ONLY

Yukarıdaki örnekte yer alan "OFFSET 0 ROWS" ifadesi hiç bir satırın es geçilmeyeceğini belirtir.

TOP'un aksine OFFSET için bir yüzdelik dilim kullanımı yerleşik olarak desteklenen bir özellik değildir fakat bir alt sorgu kullanarak bu sorunu aşabilirsiniz.

SELECT   Ad
      , Soyad
      , Eposta
FROM     dbo.DENEYSEL_TABLO
ORDER BY Ad, Soyad
OFFSET 0 ROWS    --> "0" ibaresine dikkat edin !
FETCH NEXT ( SELECT CAST(CEILING(COUNT(*) * .1) as INT) FROM dbo.Kisiler ) ROWS ONLY

Burada parantez içinde belirtilen alt sorgu yardımıyla %10'luk bir dilim elde edilebilir. Diğer varyasyonlar için hayal gücünüzü kullanabilirsiniz.

SAYFALAMA

TOP ve OFFSET deyimlerine göz attığımıza göre artık bir sayfalama örneğinin zamanı geldi sanırım. Bu noktada eğer istediğiniz şey en tepedeki kayıtlara ulaşmak ise TOP deyimini gönül rahatlığıyla kullanabilirsiniz, ORDER BY ile tatmin edici sonuçlara ulaşabilmeniz mümkün fakat amacınız belirli bir sıralamaya göre belli bir kayıt aralığını elde etmek ise OFFSET ve FETCH ikilisi sizi amacınıza çok kolay bir şekilde ulaştıracaktır. O nedenle TOP deyimini basitliği ve anlaşılırılığı kolay olduğu için örneklendirmeye gerek duymuyorum, bunun yerine OFFSET ve FETCH deyimleri için basit bir örnek vermekle konuyu tamamlayalım;

DECLARE     @SayfaNo       INT = 1 --> Hangi sayfayı istediğimizi bununla belirleyeceğiz
        ,  @SatirSayisi   INT = 5 --> Bir sayfada kaç adet kayıt olduğunu ise buradan belirteceğiz
SELECT      Ad
        ,  Soyad
        ,  EPosta
FROM        dbo.Kisiler
ORDER BY    Soyad
        ,  Ad
OFFSET      ( @SayfaNo - 1 ) * @SatirSayisi  ROWS   --> Bu formül satır sayısı ile sayfa numarası arasındaki vektörel değerin hesaplanmasını, dolayısıyla es geçilecek olan toplam satır sayısını hesaplamamızı sağlar.
FETCH NEXT  @SatirSayisi ROWS ONLY                  --> Anlaşılacağı üzere kaç satır kayıt istediğimizi burada belirttik.

MYSQL Cephesi

Konuyu MySQL açısından ele alacak olursak orada daha basit ve sade bir kullanım söz konusu. LIMIT deyimi hem TOP, hem de OFFSET & FETCH deyimlerini karşılayacak şekilde kullanılabiliyor. Bunlara basit birer örnek olması açısından aşağıdaki kodu inceleyelim;

TOP Eşdeğeri için;

SELECT Ad, Soyad, Eposta FROM Kisiler ORDER BY Soyar, Ad LIMIT 10

Yukarıdaki örnek sıralamaya göre listenin en tepesinden 10 adet satırı listeler.

OFFSET & FETCH Eşdeğeri için;

SELECT Ad, Soyad, Eposta FROM Kisiler ORDER BY Soyar, Ad LIMIT 20 , 5

Yukarıdaki örnek ise yine sıralamaya göre 20 satır es geçildikten sonra devamında gelen 5 satırı listeler.

Aşağıdaki örnek ise MySQL'de sayfalamayı parametrik hale getirebilmek için tasarlanmış bir saklı yordamı göstermektedir. Maalesef MySQL LIMIT deyiminde değişken kullanımı ile ilgili sıkıntılar çıkarıyor (En azından MySQL 5.5.27'de durum maalesef bu şekilde)

DELIMITER $$

CREATE PROCEDURE `_sp_pagination`(
IN `_SayfaNo` INT,
IN `_SatirSayisi` INT
)
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
 PREPARE SORGU FROM "SELECT Ad, Soyad, Eposta FROM Kisiler LIMIT ?, ?";
 SET @SayfaNo     = _SayfaNo - 1 * _SatirSayisi;
 SET @SatirSayisi = _SatirSayisi;
 EXECUTE SORGU USING @SayfaNo, @SatirSayisi;
DEALLOCATE PREPARE SORGU;
END$$

Kullanımı ise şuna benzer olacaktır;

CALL _sp_pagination ( 10  -- > 10. sayfadan itibaren
                       , 5            -- > 5 satır getir...
                       )

Faydalı olması dileğiyle...
YouTube Delphi Tips
"Mantıklı adam kendini dünyaya uyarlar; mantıksız adam ise dünyayı kendine uydurmakta inat eder. Bu nedenle, tüm ilerleme o inatçı adama bağlıdır." - George Bernard Shaw
WWW
Cevapla
#2
Çok Güzel bir makale olmuş ellerinize sağlık.
Unutan (Bizler) Smile için çok yararlı.
Cevapla
#3
Teşekkürler Uğur bey
Cevapla
#4
Emeğinize sağlık.
There's no place like 127.0.0.1
WWW
Cevapla
#5
Ellerine sağlık teşekkürler
Bu dünyada kendine sakladığın bilgi ahirette işine yaramaz. 
Cevapla
#6
Merhaba,
Değerli paylaşım için teşekkürler Uğur hocam.
DelphiCan'dır!
Cevapla
#7
Bende PostgreSQL tarafında örnek vereyim. LIMIT xx OFFSET yy şeklinde kullanımı mevcut.
SELECT Ad, Soyad, Eposta FROM Kisiler ORDER BY Soyar, Ad LIMIT 10 OFFSET 5
PostgreSQL - Linux - Delphi, Poliüretan
WWW
Cevapla
#8
(23-06-2018, Saat: 01:46)FiRewaLL Adlı Kullanıcıdan Alıntı: Çok Güzel bir makale olmuş ellerinize sağlık.
Unutan (Bizler) Smile için çok yararlı.

(23-06-2018, Saat: 09:11)frmman Adlı Kullanıcıdan Alıntı: Teşekkürler Uğur bey

(23-06-2018, Saat: 17:15)SimaWB Adlı Kullanıcıdan Alıntı: Emeğinize sağlık.

(23-06-2018, Saat: 20:03)adelphiforumz Adlı Kullanıcıdan Alıntı: Ellerine sağlık teşekkürler

(23-06-2018, Saat: 21:19)Fesih ARSLAN Adlı Kullanıcıdan Alıntı: Merhaba,
Değerli paylaşım için teşekkürler Uğur hocam.

Rica ederim, ben de ilginiz için teşekkür ederim.

(23-06-2018, Saat: 21:39)3ddark Adlı Kullanıcıdan Alıntı: Bende PostgreSQL tarafında örnek vereyim. LIMIT xx OFFSET yy şeklinde kullanımı mevcut.
SELECT Ad, Soyad, Eposta FROM Kisiler ORDER BY Soyar, Ad LIMIT 10 OFFSET 5

Katkılarınızdan dolayı ben de teşekkür ederim.
YouTube Delphi Tips
"Mantıklı adam kendini dünyaya uyarlar; mantıksız adam ise dünyayı kendine uydurmakta inat eder. Bu nedenle, tüm ilerleme o inatçı adama bağlıdır." - George Bernard Shaw
WWW
Cevapla
#9
elinize saglik.
Cevapla
#10
(23-06-2018, Saat: 01:07)uparlayan Adlı Kullanıcıdan Alıntı: Merhaba, bu yazıda yeni başlayanlar ve unutanlar için (bu gruba ben de dahilim Smile ) verilerin sayfalanmasını yani Pagination tekniğini fazla detaya inmeden, basite indirgenmiş bir şekilde anlatmaya çalışacağım. Daha da karmaşık hale getirmemek için performans konusuna değinmeyeceğim.

Pagination / Sayfalama neredeyse her yerde karşılaşabildiğimiz gerek masaüstü, gerek mobil, gerekse web projelerinde sıklıkla kullanılan, listelenecek olan verilerin kullanıcıya parçalar halinde "çağırılmasına" hizmet eden bir tekniktir.

Pagination'daki temel amaç listelenecek olan verilerin satır sayısını sınırlandırılması esasına dayanır, yani siz verilerin tamamını değil, belli bir aralıktakileri listelersiniz.

Bunu yapabilmek için SQL Server'da iki seçeneğimiz var, duruma ve performans maliyetine göre hangisini kullanacağınız size kalmıştır. Bunlar TOP ve OFFSET & FETCH ikilisidir.

Hem TOP, hem de OFFSET & FETCH deyimleri listelenecek olan satır sayısını sınırlandırmak için kullanılabilir fakat kullanım şekilleri hangi yöntemin sizin için en iyisi olduğunu etkileyecek düzeyde birbirinden farklılıklar arzeder.

TOP ile OFFSET & FETCH arasındaki fark nedir?

TOP Deyimi

TOP, bir sorgu sonuç kümesinin (sıralamaya göre) en tepesinden (listenin başından itibaren),  belirtilen sayı kadar satırı elde etmenizi sağlar. Örnekleme açısından aşağıdaki kodu inceleyebilirsiniz;

SELECT TOP 10
        Ad
      , Soyad
      , Eposta
FROM     dbo.Kisiler

Yukarıdaki kod, dbo.Kisiler tablosunda karşımıza çıkan ilk 10 satırı bize getirir. Her ne kadar ORDER BY, TOP kullanımı için gerekli değilmiş gibi gözükse de kullanılmasını tavsiye ederim. Sorgunun sonuna ORDER BY komutunu da eklersek listelenecek olan ilk 10 kayıt bizim belirttiğimiz sıralamaya uygun bir şekilde listelenecektir. Böylece beklenmedik verilerle karşılaşma riskinden de kurtulmuş oluruz.

SELECT TOP 10
        Ad
      , Soyad
      , Eposta
FROM     dbo.Kisiler
ORDER BY Soyad DESC

gibi...

TOP deyimini kullanırken istenen satır sayısını bir yüzde değeri olarak da belirtebiliriz. Diyelim ki 7305 adet satırı olan bir tablonuz var ve bu satırların sadece Yüzde 10'u ile ilgileniyorsunuz diyelim, bu durumda (7305 / 100) * 10 = 74 (yukarı yuvarlayacak şekilde) satır listelenecektir. Kullanımı ise şu şekilde;

SELECT TOP 10 PERCENT
        Ad
      , Soyad
      , Eposta
FROM     dbo.Kisiler
ORDER BY Soyad DESC 

Sonuç kümesinin başından itibaren belli miktarda veri çekilmesine hizmet ettiği için çoğu durumda TOP deyimi performans açısından faydalıdır. Fakat "PERCENT" ifadesi için aynı şeyi söyleyemeyiz. Percent deyiminin kullanılması söz konusu olduğunda SQL Server arka tarafta fazladan bir kaç iş daha yapar ve bu da performansı biraz etkiler. O nedenle PERCENT deyimini performans açısından pek önermem.

OFFSET ve FETCH Deyimleri

Bu iki deyim sonuç kümesinde belli bir "aralığı" elde etmek için kullanılır. OFFSET sonuç kümesinden kaç adet satırın "es geçileceğini", FETCH ise es geçilen satırlardan sonra kaç adet satır listeleneceğini belirtir.

ANSI ile uyumlu olan bu deyimler sanırım SQL Server 2012 ile birlikte sosyetenin cemiyet hayatına katıldılar Smile

OFFSET'i, FETCH deyimi olmadan kullanabilirsiniz fakat FETCH tek başına kullanılamaz. Tüm bunlarla birlikte OFFSET ve FETCH aslında "ORDER BY" deyimini genişleten iki "ek" ifadedir.

Örnek olması açısından aşağıdaki kodu inceleyelim; Bu örnekte ilk 10 kayıt es geçilecek, hemen peşi sıra, devamında gelen 10 kayıt ise listelenecektir.

SELECT   Ad
      , Soyad
      , Eposta
FROM     dbo.DENEYSEL_TABLO
ORDER BY Ad, Soyad
OFFSET 10 ROWS
FETCH NEXT 10 ROWS ONLY

Aşağıdaki örnek kullanım ise "TOP 10" ifadesiyle belirtilen kullanım ile aynı sonucu üretir;

SELECT   Ad
      , Soyad
      , Eposta
FROM     dbo.DENEYSEL_TABLO
ORDER BY Ad, Soyad
OFFSET 0 ROWS    --> "0" ibaresine dikkat edin !
FETCH NEXT 10 ROWS ONLY

Yukarıdaki örnekte yer alan "OFFSET 0 ROWS" ifadesi hiç bir satırın es geçilmeyeceğini belirtir.

TOP'un aksine OFFSET için bir yüzdelik dilim kullanımı yerleşik olarak desteklenen bir özellik değildir fakat bir alt sorgu kullanarak bu sorunu aşabilirsiniz.

SELECT   Ad
      , Soyad
      , Eposta
FROM     dbo.DENEYSEL_TABLO
ORDER BY Ad, Soyad
OFFSET 0 ROWS    --> "0" ibaresine dikkat edin !
FETCH NEXT ( SELECT CAST(CEILING(COUNT(*) * .1) as INT) FROM dbo.Kisiler ) ROWS ONLY

Burada parantez içinde belirtilen alt sorgu yardımıyla %10'luk bir dilim elde edilebilir. Diğer varyasyonlar için hayal gücünüzü kullanabilirsiniz.

SAYFALAMA

TOP ve OFFSET deyimlerine göz attığımıza göre artık bir sayfalama örneğinin zamanı geldi sanırım. Bu noktada eğer istediğiniz şey en tepedeki kayıtlara ulaşmak ise TOP deyimini gönül rahatlığıyla kullanabilirsiniz, ORDER BY ile tatmin edici sonuçlara ulaşabilmeniz mümkün fakat amacınız belirli bir sıralamaya göre belli bir kayıt aralığını elde etmek ise OFFSET ve FETCH ikilisi sizi amacınıza çok kolay bir şekilde ulaştıracaktır. O nedenle TOP deyimini basitliği ve anlaşılırılığı kolay olduğu için örneklendirmeye gerek duymuyorum, bunun yerine OFFSET ve FETCH deyimleri için basit bir örnek vermekle konuyu tamamlayalım;

DECLARE     @SayfaNo       INT = 1 --> Hangi sayfayı istediğimizi bununla belirleyeceğiz
        ,  @SatirSayisi   INT = 5 --> Bir sayfada kaç adet kayıt olduğunu ise buradan belirteceğiz
SELECT      Ad
        ,  Soyad
        ,  EPosta
FROM        dbo.Kisiler
ORDER BY    Soyad
        ,  Ad
OFFSET      ( @SayfaNo - 1 ) * @SatirSayisi  ROWS   --> Bu formül satır sayısı ile sayfa numarası arasındaki vektörel değerin hesaplanmasını, dolayısıyla es geçilecek olan toplam satır sayısını hesaplamamızı sağlar.
FETCH NEXT  @SatirSayisi ROWS ONLY                  --> Anlaşılacağı üzere kaç satır kayıt istediğimizi burada belirttik.

MYSQL Cephesi

Konuyu MySQL açısından ele alacak olursak orada daha basit ve sade bir kullanım söz konusu. LIMIT deyimi hem TOP, hem de OFFSET & FETCH deyimlerini karşılayacak şekilde kullanılabiliyor. Bunlara basit birer örnek olması açısından aşağıdaki kodu inceleyelim;

TOP Eşdeğeri için;

SELECT Ad, Soyad, Eposta FROM Kisiler ORDER BY Soyar, Ad LIMIT 10

Yukarıdaki örnek sıralamaya göre listenin en tepesinden 10 adet satırı listeler.

OFFSET & FETCH Eşdeğeri için;

SELECT Ad, Soyad, Eposta FROM Kisiler ORDER BY Soyar, Ad LIMIT 20 , 5

Yukarıdaki örnek ise yine sıralamaya göre 20 satır es geçildikten sonra devamında gelen 5 satırı listeler.

Aşağıdaki örnek ise MySQL'de sayfalamayı parametrik hale getirebilmek için tasarlanmış bir saklı yordamı göstermektedir. Maalesef MySQL LIMIT deyiminde değişken kullanımı ile ilgili sıkıntılar çıkarıyor (En azından MySQL 5.5.27'de durum maalesef bu şekilde)

DELIMITER $$

CREATE PROCEDURE `_sp_pagination`(
IN `_SayfaNo` INT,
IN `_SatirSayisi` INT
)
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
 PREPARE SORGU FROM "SELECT Ad, Soyad, Eposta FROM Kisiler LIMIT ?, ?";
 SET @SayfaNo     = _SayfaNo - 1 * _SatirSayisi;
 SET @SatirSayisi = _SatirSayisi;
 EXECUTE SORGU USING @SayfaNo, @SatirSayisi;
DEALLOCATE PREPARE SORGU;
END$$

Kullanımı ise şuna benzer olacaktır;

CALL _sp_pagination ( 10  -- > 10. sayfadan itibaren
                       , 5            -- > 5 satır getir...
                       )

Faydalı olması dileğiyle..
hocam bende ofset komutu çalışmıyor firebird versiyonundanmı acaba firebird 2.5 kullanıyorum 
select ARSIVNO  from MUSTERILER  ORDER BY ARSIVNO  OFFSET 0 ROWS FETCH NEXT 2 ROWS ONLY
Cevapla


Konu ile Alakalı Benzer Konular
Konular Yazar Yorumlar Okunma Son Yorum
  Sql Server Veritabanı Bozulmaları Tespit ve Önleme Yöntemleri adelphiforumz 4 5.313 20-01-2020, Saat: 17:08
Son Yorum: Bay_Y
  SQL Server : Trigger hangi kipte çalışıyor uparlayan 10 11.539 18-01-2020, Saat: 09:24
Son Yorum: serdar
  30 Adet MS SQL Server Performans İpucu csunguray 6 8.344 09-10-2019, Saat: 09:19
Son Yorum: csunguray
  SQL Server sp_executesql ile çalıştırılan sorguya tabloyu parametre olarak göndermek sabanakman 6 7.181 17-09-2018, Saat: 12:34
Son Yorum: sabanakman
  SQL Server : Tablolar için parametrik sıralı alan listesi uparlayan 6 7.919 16-07-2018, Saat: 18:36
Son Yorum: ssahinoglu



Konuyu Okuyanlar: 1 Ziyaretçi