SQL de sıralama (Ranking) fonksiyonları ile çektiğimiz sorguları belirli bir kritere göre sıralayıp o şekilde kullanabiliriz. İstersek grup grup sıralandırabilir, istersek dogrudan 1,2,3... şeklinde sıralandırabilir, istersek yarışma vs. gibi kullanımlar için örneğin eğer iki tane 2.varsa bi sonraki 4. olacak şekilde 1,2,4... şeklinde sıralandırabiliriz. Şimdi bunların hepsini tek tek ele alacağız.
Öncelikle tablomuzdan örnek bi veri sorgulayıp tablonun sıralandırılmamış haline göz atalım;
select
ad,soyad,sehir,yas
from
tbKisiler
ad | soyad | sehir | yas |
---|---|---|---|
Cahit | ÇEÇEN | ANKARA | 21 |
Emre | ÜNAL | ESKİŞEHİR | 19 |
Faruk | ÜNAL | ESKİŞEHİR | 21 |
Fatih | KAYA | ANKARA | 22 |
Necip | ULU | ANKARA | 37 |
Osman | HIZLI | ANKARA | 33 |
Osman | ÜNAL | ŞANLIURFA | 67 |
Özgü | ADEM | ŞANLIURFA | 21 |
ROW_NUMBER Fonksiyonu
Çekilen sorgu sonucu için ilk satırdan başlayarak 1,2,3... şeklinde artan değerler üretir. İki çeşit kullanımı söz konusudur. İstersek belirli bi kolona göre gruplayarak sıralandırabilir, yada istersek gruplandırma olmadan direk sıralandırabiliriz.
ROW_NUMBER ( ) OVER ( [partition_by_clause] order_by_clause)
Burada partition by ifadesini kullanırsak gruplama yaparak sıralama yapmış oluruz. Gruplanan kolon değiştikçe numara yeniden 1den başlayarak numerik olarak artmaya devam eder. Eğer partition by ifadesini kullanmadan direk order by kısmına geçersek bu sefer bütün satırlar genel olarak gruplanma olmadan sıralandırılır.
select
Row_number() over(
order
by
yas),ad,soyad,tel,yas
from
tbKisiler
Column1 | ad | soyad | sehir | yas |
---|---|---|---|---|
1 | Emre | ÜNAL | ESKİŞEHİR | 19 |
2 | Faruk | ÜNAL | ESKİŞEHİR | 21 |
3 | Cahit | ÇEÇEN | ANKARA | 21 |
4 | Özgü | ADEM | ŞANLIURFA | 21 |
5 | Fatih | KAYA | ANKARA | 22 |
6 | Osman | HIZLI | ANKARA | 33 |
7 | Necip | ULU | ANKARA | 37 |
8 | Osman | ÜNAL | ŞANLIURFA | 67 |
yukarıdaki tabloda görüldüğü gibi Row_number() over(
order
by
yas)
ifadesi ile yas kolonuna göre sıralandırma yapılmış ve numara verilmiştir.
Burda dikkat edilmesi gereken bir nokta var. Sorgumuzda order by ifadesi kullanmadığımızdan sorgu row_number() fonksiyonuna göre sıralandı. Ama eger sorguda order by ifadesine yer verirsek bu kez tablo sorgunun sıralamasına göre sıralanacak fakat satır numarası atama işleminde atanan değerler Row_number() over(
order
by
yas)
ifadesindeki order by sıralamasına göre atanacaktır. Örnekle iki tabloyu karşılaştırarak daha iyi anlayacağız.
select
Row_number() over(
order
by
yas),ad,soyad,sehir,yas
from
tbKisiler
order
by
ad
Column1 | ad | soyad | sehir | yas |
---|---|---|---|---|
3 | Cahit | ÇEÇEN | ANKARA | 21 |
1 | Emre | ÜNAL | ESKİŞEHİR | 19 |
2 | Faruk | ÜNAL | ESKİŞEHİR | 21 |
5 | Fatih | KAYA | ANKARA | 22 |
7 | Necip | ULU | ANKARA | 37 |
8 | Osman | ÜNAL | ŞANLIURFA | 67 |
6 | Osman | HIZLI | ANKARA | 33 |
4 | Özgü | ADEM | ŞANLIURFA | 21 |
Gördüğünüz gibi tablo ad kolonuna göre sıralandı fakat satır numaraları yas sıralamasına göre verildi. Bu kullanım türü diğerine istinaden pek kullanılmamaktadır ama yinede karşılaşabilirsiniz.
Şimdi de partition by ifadesi ile gruplandırma yaparak numaralandırma yapalım. Şehirlere göre gruplandırıp yaş sıralamasına göre sorgulayalım.
select
Row_number() over(PARTITION
BY
sehir
order
by
yas),ad,soyad,sehir,yas
from
tbKisiler
Column1 | ad | soyad | sehir | yas |
---|---|---|---|---|
1 | Cahit | ÇEÇEN | ANKARA | 21 |
2 | Fatih | KAYA | ANKARA | 22 |
3 | Osman | HIZLI | ANKARA | 33 |
4 | Necip | ULU | ANKARA | 37 |
1 | Emre | ÜNAL | ESKİŞEHİR | 19 |
2 | Faruk | ÜNAL | ESKİŞEHİR | 21 |
1 | Özgü | ADEM | ŞANLIURFA | 21 |
2 | Osman | ÜNAL | ŞANLIURFA | 67 |
Tabloda gördüğünüz gibi her şehir için sıralama 1den başlayarak artıyor ve sıralama her şehir için yaşa göre yapılmış durumda, başka bir şehre geçildiğinde o şehirdekiler için sıralama yeniden başlıyor ve her şehirde bulunanlar yaş sıralamasına göre listelenmiş durumdalar.
RANK Fonksiyonu
RANK fonksiyonu da ROW_NUMBER fonksiyonuna benzer şekilde çalışmaktadır. Aralarındaki tek fark RANK ile sıralama yapılırken aynı değerdeki kolonlara aynı sıra numarası verilir, arkalarındakine ise bunlara farklı verilmiş gibi düşünülerek denk gelen sıra numarasını verilir.
RANK( ) OVER ( [partition_by_clause] order_by_clause)
Kullanımı aynı ROW_NUMBER Fonksiyonu gibidir, aralarındaki farkı daha iyi anlamak için aşağıdaki örneği inceleyelim.
Mesela yaş sıralamasına göre sorgumuzu çektik ve her kişi için kendisinden genç kaç kişi olduğunu öğrenmek istiyoruz, bunu şu şekilde yapabiliriz.
select
RANK() over(
order
by
yas),ad,soyad,sehir,yas
from
tbKisiler
Column1 | ad | soyad | sehir | yas |
---|---|---|---|---|
1 | Emre | ÜNAL | ESKİŞEHİR | 19 |
2 | Faruk | ÜNAL | ESKİŞEHİR | 21 |
2 | Cahit | ÇEÇEN | ANKARA | 21 |
2 | Özgü | ADEM | ŞANLIURFA | 21 |
5 | Fatih | KAYA | ANKARA | 22 |
6 | Osman | HIZLI | ANKARA | 33 |
7 | Necip | ULU | ANKARA | 37 |
8 | Osman | ÜNAL | ŞANLIURFA | 67 |
tabloya baktığımızda Fatih Kaya yı inceleyecek olursak 5.sırada olduğunu görürüz. yani kendisinden genç 4kişi var demektir. Listeye baktığımızda gerçekten de Fatih Kaya dan genç 4 kişinin olduğunu görüyoruz. Diğer yandan Faruk, Cahit ve Özgü 2.sıradalar. yani kendilerinden genç 1 kişinin olduğunu anlıyoruz ve nitekim bu da doğru. Burda Faruk, Cahit ve Özgü aynı yaşta olduğundan aralarında bir sıralama yapılamıyor ve üçünede 2.sıralama numarası denk geliyor. Bu örneği yarışma sonuçları içn vs. kullanabilirsiniz.
Burada aynı değerdeki kişilere aynı numaraları vermiş ve bir sonraki kişiye bunların sayısınca sıralandırmayı dewam ettirerek numara vermiştik. Bu şekilde yapmayıp tekrar eden kayıtlardan sonra yine numerik olarak sıralandırmaya devam etmek istersek DENSE_RANK() Fonksiyonunu kullanmamız gerekir.
select
DENSE_RANK() over(
order
by
yas),ad,soyad,sehir,yas
from
tbKisiler
Column1 | ad | soyad | sehir | yas |
---|---|---|---|---|
1 | Emre | ÜNAL | ESKİŞEHİR | 19 |
2 | Faruk | ÜNAL | ESKİŞEHİR | 21 |
2 | Cahit | ÇEÇEN | ANKARA | 21 |
2 | Özgü | ADEM | ŞANLIURFA | 21 |
3 | Fatih | KAYA | ANKARA | 22 |
4 | Osman | HIZLI | ANKARA | 33 |
5 | Necip | ULU | ANKARA | 37 |
6 | Osman | ÜNAL | ŞANLIURFA | 67 |
Dense_Rank() Fonksiyonunun kullanımı da diğerleri ile aynı şekildedir
DENSE_RANK( ) OVER ( [partition_by_clause] order_by_clause)
NTILE Fonksiyonu
NTILE fonksiyonu üstteki sıralama fonksiyonlarından biraz farklıdır. Dışarıdan girilen sayıya bağlı olarak sorgu sonucundaki satırları gruplar. Bu gruplama işlemini yaparken sorgu sonucundaki satır sayısını girdiğimiz sayıya bölerek her bir grubun kaç elemanlı olacağı hesaplanır. Yani bi grup en fazla sorgu sonucunun girilen sayıya bölümü kadar satır içerebilir.
Bunu örnekle incelersek 21 odalı bir oteldeki otel odalarını NTILE 4e göre gruplarsak gruplardaki satır sayısı şu şekilde olur;
Birinci grup: 21/4=5,25 sonuç yukarı yuvarlanır ve ilk grup 6 elemanlı olur,
İkinci grup: 21-6=15 -> 15/3=5 ikinci grup 5 elemanlı olur
Üçüncü grup: 15-5=10 -> 10/2=5 üçüncü grup 5 elemanlı olur
Dördüncü grup : 10-5=5 -> 5/1=5 dördüncü grup 5 elemanlı olur
select
NTILE(4) OVER (
order
by
odaAdi),odaAdi
from
tbOtel
Column1 | odaAdi |
---|---|
1 | ODA 01 |
1 | ODA 02 |
1 | ODA 03 |
1 | ODA 04 |
1 | ODA 05 |
1 | ODA 06 |
2 | ODA 07 |
2 | ODA 08 |
2 | ODA 09 |
2 | ODA 10 |
2 | ODA 11 |
3 | ODA 12 |
3 | ODA 13 |
3 | ODA 14 |
3 | ODA 15 |
3 | ODA 16 |
4 | ODA 17 |
4 | ODA 18 |
4 | ODA 19 |
4 | ODA 20 |
4 | ODA 21 |