{"id":149,"date":"2019-09-30T22:12:41","date_gmt":"2019-09-30T19:12:41","guid":{"rendered":"http:\/\/www.potansif.com\/?p=149"},"modified":"2019-09-30T22:12:41","modified_gmt":"2019-09-30T19:12:41","slug":"sql-server-ve-mysql-ile-sayfalama-pagination","status":"publish","type":"post","link":"http:\/\/www.potansif.com\/?p=149","title":{"rendered":"SQL Server ve MySQL ile Sayfalama, Pagination"},"content":{"rendered":"<p>Merhaba, bu yaz\u0131da yeni ba\u015flayanlar ve unutanlar i\u00e7in (bu gruba ben de dahilim \ud83d\ude42 ) verilerin sayfalanmas\u0131n\u0131 yani Pagination tekni\u011fini fazla detaya inmeden, basite indirgenmi\u015f bir \u015fekilde anlatmaya \u00e7al\u0131\u015faca\u011f\u0131m. Daha da karma\u015f\u0131k hale getirmemek i\u00e7in performans konusuna de\u011finmeyece\u011fim.<br \/>\n<!--more--><br \/>\nPagination \/ Sayfalama neredeyse her yerde kar\u015f\u0131la\u015fabildi\u011fimiz gerek masa\u00fcst\u00fc, gerek mobil, gerekse web projelerinde s\u0131kl\u0131kla kullan\u0131lan, listelenecek olan verilerin kullan\u0131c\u0131ya par\u00e7alar halinde &#8220;\u00e7a\u011f\u0131r\u0131lmas\u0131na&#8221; hizmet eden bir tekniktir.<\/p>\n<p>Pagination&#8217;daki temel ama\u00e7 listelenecek olan verilerin sat\u0131r say\u0131s\u0131n\u0131 s\u0131n\u0131rland\u0131r\u0131lmas\u0131 esas\u0131na dayan\u0131r, yani siz verilerin tamam\u0131n\u0131 de\u011fil, belli bir aral\u0131ktakileri listelersiniz.<\/p>\n<p>Bunu yapabilmek i\u00e7in SQL Server&#8217;da iki se\u00e7ene\u011fimiz var, duruma ve performans maliyetine g\u00f6re hangisini kullanaca\u011f\u0131n\u0131z size kalm\u0131\u015ft\u0131r. Bunlar TOP ve OFFSET &amp; FETCH ikilisidir.<\/p>\n<p>Hem TOP, hem de OFFSET &amp; FETCH deyimleri listelenecek olan sat\u0131r say\u0131s\u0131n\u0131 s\u0131n\u0131rland\u0131rmak i\u00e7in kullan\u0131labilir fakat kullan\u0131m \u015fekilleri hangi y\u00f6ntemin sizin i\u00e7in en iyisi oldu\u011funu etkileyecek d\u00fczeyde birbirinden farkl\u0131l\u0131klar arzeder.<\/p>\n<h1>TOP ile OFFSET &amp; FETCH aras\u0131ndaki fark nedir?<\/h1>\n<h2>TOP Deyimi<\/h2>\n<p>TOP, bir sorgu sonu\u00e7 k\u00fcmesinin (s\u0131ralamaya g\u00f6re) en tepesinden (listenin ba\u015f\u0131ndan itibaren), &nbsp;belirtilen say\u0131 kadar sat\u0131r\u0131 elde etmenizi sa\u011flar. \u00d6rnekleme a\u00e7\u0131s\u0131ndan a\u015fa\u011f\u0131daki kodu inceleyebilirsiniz;<\/p>\n<pre><code>SELECT TOP 10\n&nbsp; &nbsp; &nbsp;  &nbsp; Ad\n&nbsp; &nbsp; &nbsp;  , Soyad\n&nbsp; &nbsp; &nbsp;  , Eposta\nFROM   &nbsp; dbo.Kisiler<\/code><\/pre>\n<p>Yukar\u0131daki kod, dbo.Kisiler tablosunda kar\u015f\u0131m\u0131za \u00e7\u0131kan ilk 10 sat\u0131r\u0131 bize getirir. Her ne kadar ORDER BY, TOP kullan\u0131m\u0131 i\u00e7in gerekli de\u011filmi\u015f gibi g\u00f6z\u00fckse de kullan\u0131lmas\u0131n\u0131 tavsiye ederim. Sorgunun sonuna ORDER BY komutunu da eklersek listelenecek olan ilk 10 kay\u0131t bizim belirtti\u011fimiz s\u0131ralamaya uygun bir \u015fekilde listelenecektir. B\u00f6ylece beklenmedik verilerle kar\u015f\u0131la\u015fma riskinden de kurtulmu\u015f oluruz.<\/p>\n<pre><code>SELECT TOP 10\n&nbsp; &nbsp; &nbsp;  &nbsp; Ad\n&nbsp; &nbsp; &nbsp;  , Soyad\n&nbsp; &nbsp; &nbsp;  , Eposta\nFROM &nbsp; &nbsp; dbo.Kisiler\nORDER BY Soyad DESC<\/code><\/pre>\n<p>gibi&#8230;<\/p>\n<p>TOP deyimini kullan\u0131rken istenen sat\u0131r say\u0131s\u0131n\u0131 bir y\u00fczde de\u011feri olarak da belirtebiliriz. Diyelim ki 7305 adet sat\u0131r\u0131 olan bir tablonuz var ve bu sat\u0131rlar\u0131n sadece Y\u00fczde 10&#8217;u ile ilgileniyorsunuz diyelim, bu durumda (7305 \/ 100) * 10 = 74 (yukar\u0131 yuvarlayacak \u015fekilde) sat\u0131r listelenecektir. Kullan\u0131m\u0131 ise \u015fu \u015fekilde;<\/p>\n<pre><code>SELECT TOP 10 PERCENT\n&nbsp; &nbsp; &nbsp;  &nbsp; Ad\n&nbsp; &nbsp; &nbsp;  , Soyad\n&nbsp; &nbsp; &nbsp;  , Eposta\nFROM &nbsp; &nbsp; dbo.Kisiler\nORDER BY Soyad DESC <\/code><\/pre>\n<p>Sonu\u00e7 k\u00fcmesinin ba\u015f\u0131ndan itibaren belli miktarda veri \u00e7ekilmesine hizmet etti\u011fi i\u00e7in \u00e7o\u011fu durumda TOP deyimi performans a\u00e7\u0131s\u0131ndan faydal\u0131d\u0131r. Fakat &#8220;PERCENT&#8221; ifadesi i\u00e7in ayn\u0131 \u015feyi s\u00f6yleyemeyiz. Percent deyiminin kullan\u0131lmas\u0131 s\u00f6z konusu oldu\u011funda SQL Server arka tarafta fazladan bir ka\u00e7 i\u015f daha yapar ve bu da performans\u0131 biraz etkiler. O nedenle PERCENT deyimini performans a\u00e7\u0131s\u0131ndan pek \u00f6nermem.<\/p>\n<h2>OFFSET ve FETCH Deyimleri<\/h2>\n<p>Bu iki deyim sonu\u00e7 k\u00fcmesinde belli bir &#8220;aral\u0131\u011f\u0131&#8221; elde etmek i\u00e7in kullan\u0131l\u0131r. OFFSET sonu\u00e7 k\u00fcmesinden ka\u00e7 adet sat\u0131r\u0131n &#8220;es ge\u00e7ilece\u011fini&#8221;, FETCH ise es ge\u00e7ilen sat\u0131rlardan sonra ka\u00e7 adet sat\u0131r listelenece\u011fini belirtir.<\/p>\n<p>ANSI ile uyumlu olan bu deyimler san\u0131r\u0131m SQL Server 2012 ile birlikte sosyetenin cemiyet hayat\u0131na kat\u0131ld\u0131lar \ud83d\ude42<\/p>\n<p>OFFSET&#8217;i, FETCH deyimi olmadan kullanabilirsiniz fakat FETCH tek ba\u015f\u0131na kullan\u0131lamaz. T\u00fcm bunlarla birlikte OFFSET ve FETCH asl\u0131nda &#8220;ORDER BY&#8221; deyimini geni\u015fleten iki &#8220;ek&#8221; ifadedir.<\/p>\n<p>\u00d6rnek olmas\u0131 a\u00e7\u0131s\u0131ndan a\u015fa\u011f\u0131daki kodu inceleyelim; Bu \u00f6rnekte ilk 10 kay\u0131t es ge\u00e7ilecek, hemen pe\u015fi s\u0131ra, devam\u0131nda gelen 10 kay\u0131t ise listelenecektir.<\/p>\n<pre><code>SELECT &nbsp; Ad\n&nbsp; &nbsp; &nbsp; , Soyad\n&nbsp; &nbsp; &nbsp; , Eposta\nFROM &nbsp; &nbsp; dbo.DENEYSEL_TABLO\nORDER BY Ad, Soyad\nOFFSET 10 ROWS\nFETCH NEXT 10 ROWS ONLY<\/code><\/pre>\n<p>A\u015fa\u011f\u0131daki \u00f6rnek kullan\u0131m ise &#8220;TOP 10&#8221; ifadesiyle belirtilen kullan\u0131m ile ayn\u0131 sonucu \u00fcretir;<\/p>\n<pre><code>SELECT &nbsp;  Ad\n&nbsp; &nbsp;  &nbsp; , Soyad\n&nbsp; &nbsp;  &nbsp; , Eposta\nFROM &nbsp; &nbsp; dbo.DENEYSEL_TABLO\nORDER BY Ad, Soyad\nOFFSET 0 ROWS &nbsp; &nbsp;--&gt; \"0\" ibaresine dikkat edin !\nFETCH NEXT 10 ROWS ONLY<\/code><\/pre>\n<p>Yukar\u0131daki \u00f6rnekte yer alan &#8220;OFFSET 0 ROWS&#8221; ifadesi hi\u00e7 bir sat\u0131r\u0131n es ge\u00e7ilmeyece\u011fini belirtir.<\/p>\n<p>TOP&#8217;un aksine OFFSET i\u00e7in bir y\u00fczdelik dilim kullan\u0131m\u0131 yerle\u015fik olarak desteklenen bir \u00f6zellik de\u011fildir fakat bir alt sorgu kullanarak bu sorunu a\u015fabilirsiniz.<\/p>\n<pre><code>SELECT &nbsp;  Ad\n &nbsp; &nbsp; &nbsp; , Soyad\n &nbsp; &nbsp; &nbsp; , Eposta\nFROM &nbsp; &nbsp; dbo.DENEYSEL_TABLO\nORDER BY Ad, Soyad\nOFFSET 0 ROWS &nbsp; &nbsp;--&gt; \"0\" ibaresine dikkat edin !\nFETCH NEXT ( SELECT CAST(CEILING(COUNT(*) * .1) as INT) FROM dbo.Kisiler ) ROWS ONLY<\/code><\/pre>\n<p>Burada parantez i\u00e7inde belirtilen alt sorgu yard\u0131m\u0131yla %10&#8217;luk bir dilim elde edilebilir. Di\u011fer varyasyonlar i\u00e7in hayal g\u00fcc\u00fcn\u00fcz\u00fc kullanabilirsiniz.<\/p>\n<h1>SAYFALAMA<\/h1>\n<p>TOP ve OFFSET deyimlerine g\u00f6z att\u0131\u011f\u0131m\u0131za g\u00f6re art\u0131k bir sayfalama \u00f6rne\u011finin zaman\u0131 geldi san\u0131r\u0131m. Bu noktada e\u011fer istedi\u011finiz \u015fey en tepedeki kay\u0131tlara ula\u015fmak ise TOP deyimini g\u00f6n\u00fcl rahatl\u0131\u011f\u0131yla kullanabilirsiniz, ORDER BY ile tatmin edici sonu\u00e7lara ula\u015fabilmeniz m\u00fcmk\u00fcn fakat amac\u0131n\u0131z belirli bir s\u0131ralamaya g\u00f6re belli bir kay\u0131t aral\u0131\u011f\u0131n\u0131 elde etmek ise OFFSET ve FETCH ikilisi sizi amac\u0131n\u0131za \u00e7ok kolay bir \u015fekilde ula\u015ft\u0131racakt\u0131r. O nedenle TOP deyimini basitli\u011fi ve anla\u015f\u0131l\u0131r\u0131l\u0131\u011f\u0131 kolay oldu\u011fu i\u00e7in \u00f6rneklendirmeye gerek duymuyorum, bunun yerine OFFSET ve FETCH deyimleri i\u00e7in basit bir \u00f6rnek vermekle konuyu tamamlayal\u0131m;<\/p>\n<pre><code>DECLARE &nbsp; &nbsp; @SayfaNo &nbsp; &nbsp; &nbsp; INT = 1 --&gt; Hangi sayfay\u0131 istedi\u011fimizi bununla belirleyece\u011fiz\n&nbsp; &nbsp; &nbsp; &nbsp; , &nbsp;@SatirSayisi &nbsp; INT = 5 --&gt; Bir sayfada ka\u00e7 adet kay\u0131t oldu\u011funu ise buradan belirtece\u011fiz\nSELECT &nbsp; &nbsp; &nbsp;Ad\n&nbsp; &nbsp; &nbsp; &nbsp; , &nbsp;Soyad\n&nbsp; &nbsp; &nbsp; &nbsp; , &nbsp;EPosta\nFROM &nbsp; &nbsp; &nbsp; &nbsp;dbo.Kisiler\nORDER BY &nbsp; &nbsp;Soyad\n&nbsp; &nbsp; &nbsp; &nbsp; , &nbsp;Ad\nOFFSET &nbsp; &nbsp; &nbsp;( @SayfaNo - 1 ) * @SatirSayisi &nbsp;ROWS &nbsp; --&gt; Bu form\u00fcl sat\u0131r say\u0131s\u0131 ile sayfa numaras\u0131 aras\u0131ndaki vekt\u00f6rel de\u011ferin hesaplanmas\u0131n\u0131, dolay\u0131s\u0131yla es ge\u00e7ilecek olan toplam sat\u0131r say\u0131s\u0131n\u0131 hesaplamam\u0131z\u0131 sa\u011flar.\nFETCH NEXT &nbsp;@SatirSayisi ROWS ONLY &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;--&gt; Anla\u015f\u0131laca\u011f\u0131 \u00fczere ka\u00e7 sat\u0131r kay\u0131t istedi\u011fimizi burada belirttik.<\/code><\/pre>\n<h1>MYSQL Cephesi<\/h1>\n<p>Konuyu MySQL a\u00e7\u0131s\u0131ndan ele alacak olursak orada daha basit ve sade bir kullan\u0131m s\u00f6z konusu. LIMIT deyimi hem TOP, hem de OFFSET &amp; FETCH deyimlerini kar\u015f\u0131layacak \u015fekilde kullan\u0131labiliyor. Bunlara basit birer \u00f6rnek olmas\u0131 a\u00e7\u0131s\u0131ndan a\u015fa\u011f\u0131daki kodu inceleyelim;<\/p>\n<h1>TOP E\u015fde\u011feri i\u00e7in;<\/h1>\n<pre><code>SELECT Ad, Soyad, Eposta FROM Kisiler ORDER BY Soyar, Ad LIMIT 10<\/code><\/pre>\n<p>Yukar\u0131daki \u00f6rnek s\u0131ralamaya g\u00f6re listenin en tepesinden 10 adet sat\u0131r\u0131 listeler.<\/p>\n<h1>OFFSET &amp; FETCH E\u015fde\u011feri i\u00e7in;<\/h1>\n<pre><code>SELECT Ad, Soyad, Eposta FROM Kisiler ORDER BY Soyar, Ad LIMIT 20 , 5<\/code><\/pre>\n<p>Yukar\u0131daki \u00f6rnek ise yine s\u0131ralamaya g\u00f6re 20 sat\u0131r es ge\u00e7ildikten sonra devam\u0131nda gelen 5 sat\u0131r\u0131 listeler.<\/p>\n<p>A\u015fa\u011f\u0131daki \u00f6rnek ise MySQL&#8217;de sayfalamay\u0131 parametrik hale getirebilmek i\u00e7in tasarlanm\u0131\u015f bir sakl\u0131 yordam\u0131 g\u00f6stermektedir. Maalesef MySQL LIMIT deyiminde de\u011fi\u015fken kullan\u0131m\u0131 ile ilgili s\u0131k\u0131nt\u0131lar \u00e7\u0131kar\u0131yor (En az\u0131ndan MySQL 5.5.27&#8217;de durum maalesef bu \u015fekilde)<\/p>\n<pre><code>\nDELIMITER $\n\nCREATE PROCEDURE `_sp_pagination`(\nIN `_SayfaNo` INT,\nIN `_SatirSayisi` INT\n)\nLANGUAGE SQL\nDETERMINISTIC\nCONTAINS SQL\nSQL SECURITY DEFINER\nCOMMENT ''\nBEGIN\n&nbsp;PREPARE SORGU FROM \"SELECT Ad, Soyad, Eposta FROM Kisiler LIMIT ?, ?\";\n&nbsp;SET @SayfaNo &nbsp; &nbsp; = _SayfaNo - 1 * _SatirSayisi;\n&nbsp;SET @SatirSayisi = _SatirSayisi;\n&nbsp;EXECUTE SORGU USING @SayfaNo, @SatirSayisi;\nDEALLOCATE PREPARE SORGU;\nEND$<\/code><\/pre>\n<p>Kullan\u0131m\u0131 ise \u015funa benzer olacakt\u0131r;<\/p>\n<pre><code>CALL _sp_pagination ( 10&nbsp; -- &gt; 10. sayfadan itibaren\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;, 5 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;-- &gt; 5 sat\u0131r getir...\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;)<\/code><\/pre>\n<p>Faydal\u0131 olmas\u0131 dile\u011fiyle&#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Merhaba, bu yaz\u0131da yeni ba\u015flayanlar ve unutanlar i\u00e7in (bu gruba ben de dahilim \ud83d\ude42 ) verilerin sayfalanmas\u0131n\u0131 yani Pagination tekni\u011fini fazla detaya inmeden, basite indirgenmi\u015f bir \u015fekilde anlatmaya \u00e7al\u0131\u015faca\u011f\u0131m. Daha da karma\u015f\u0131k hale getirmemek i\u00e7in performans konusuna de\u011finmeyece\u011fim.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[9,10,11,12,7],"class_list":["post-149","post","type-post","status-publish","format-standard","hentry","category-blog","tag-mysql","tag-pagination","tag-programlama","tag-sayfalama","tag-sql-server"],"_links":{"self":[{"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/posts\/149","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.potansif.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=149"}],"version-history":[{"count":1,"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/posts\/149\/revisions"}],"predecessor-version":[{"id":150,"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/posts\/149\/revisions\/150"}],"wp:attachment":[{"href":"http:\/\/www.potansif.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=149"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.potansif.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=149"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.potansif.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=149"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}