Ders 04 / 18
Sıralama ve Sınırlama
Sonuç kümesinin sıralanması, çok anahtarlı sıralama, harmanlamanın sıra üzerindeki etkisi, boş değerlerin yeri ve sonucu ilk satırlarla sınırlamanın standart ile yaygın yazımları.
İçindekiler
Önceki üç ders hangi sütunların ve hangi satırların döneceğini belirledi. Hiçbiri satırların hangi sırayla döneceğini söylemedi. Çıktılarda görülen sıra motorun tabloyu okuma biçiminden geliyordu; aynı sorgu farklı bir plan seçildiğinde farklı sırada dönebilir.
İlişkisel modelde bir bağıntı sırasız bir küme olduğu için bu şaşırtıcı değil: sıra, verinin değil sorgunun bir özelliğidir. Sıra isteniyorsa açıkça yazılmalıdır. Bu ders sıralama yan tümcesini ve onunla birlikte anlam kazanan sınırlama yazımını kurar.
Aşağıdaki blok şemayı ve örnek veriyi kurar; dersin bütün sorguları bu blokta oluşturulan
kutuphane.db dosyası üzerinde çalışır.
rm -f kutuphane.db sqlite3 kutuphane.db <<'SQL' CREATE TABLE sube (sube_id INTEGER PRIMARY KEY, ad TEXT NOT NULL, sehir TEXT NOT NULL); CREATE TABLE kitap (kitap_id INTEGER PRIMARY KEY, baslik TEXT NOT NULL, yazar TEXT NOT NULL, basim_yili INTEGER, sube_id INTEGER REFERENCES sube(sube_id)); CREATE TABLE uye (uye_id INTEGER PRIMARY KEY, ad TEXT NOT NULL, soyad TEXT NOT NULL, eposta TEXT, kayit_tarihi TEXT NOT NULL); CREATE TABLE odunc (odunc_id INTEGER PRIMARY KEY, kitap_id INTEGER NOT NULL REFERENCES kitap(kitap_id), uye_id INTEGER NOT NULL REFERENCES uye(uye_id), alis_tarihi TEXT NOT NULL, iade_tarihi TEXT); INSERT INTO sube VALUES (1,'Merkez','Ankara'),(2,'Bahçelievler','Ankara'), (3,'Kadıköy','İstanbul'),(4,'Konak','İzmir'); INSERT INTO kitap VALUES (1,'Körlük','José Saramago',1995,1),(2,'Tutunamayanlar','Oğuz Atay',1972,1), (3,'Kum Kitabı','Jorge Luis Borges',1975,2),(4,'Yaban','Yakup Kadri',1932,2), (5,'Sessiz Ev','Orhan Pamuk',1983,3),(6,'Anayurt Oteli','Yusuf Atılgan',NULL,3), (7,'Tehlikeli Oyunlar','Oğuz Atay',1973,NULL); INSERT INTO uye VALUES (1,'Ayşe','Demir','[email protected]','2023-02-14'), (2,'Mehmet','Kaya','[email protected]','2023-05-30'),(3,'Zeynep','Arslan',NULL,'2024-01-09'), (4,'Emre','Yıldız','[email protected]','2024-03-22'),(5,'Selin','Aydın',NULL,'2024-11-05'), (6,'Burak','Şahin','[email protected]','2025-01-18'); INSERT INTO odunc VALUES (1,1,1,'2025-01-10','2025-01-24'),(2,2,1,'2025-02-02','2025-02-20'), (3,1,2,'2025-02-11',NULL),(4,3,3,'2025-03-01','2025-03-15'),(5,4,3,'2025-03-18','2025-04-02'), (6,1,4,'2025-04-05','2025-04-19'),(7,5,4,'2025-04-21',NULL),(8,2,5,'2025-05-02','2025-05-30'), (9,7,1,'2025-05-14','2025-05-28'),(10,3,5,'2025-06-03',NULL),(11,6,2,'2025-06-11','2025-06-25'), (12,4,4,'2025-06-20','2025-07-04'); SQL
Tek Anahtarla Sıralama
ORDER BY yan tümcesi sıralama anahtarını alır. Yön belirtilmezse artan sıra
varsayılır; ASC ve DESC yönü açıkça yazar.
sqlite3 kutuphane.db <<'SQL' .headers on .mode column SELECT baslik, basim_yili FROM kitap ORDER BY basim_yili; SQL
baslik basim_yili ----------------- ---------- Anayurt Oteli Yaban 1932 Tutunamayanlar 1972 Tehlikeli Oyunlar 1973 Kum Kitabı 1975 Sessiz Ev 1983 Körlük 1995
Basım yılı bilinmeyen kitap en başa geldi. Boş değerin sıralamadaki yeri kuramsal olarak belirsizdir — bilinmeyen bir sayının 1932’den büyük mü küçük mü olduğu söylenemez — bu yüzden motorlar bir varsayım yapar ve bu varsayım motora göre değişir. Bazıları boş değerleri artan sıralamada başa, bazıları sona koyar.
sqlite3 kutuphane.db <<'SQL' .headers on .mode column SELECT baslik, basim_yili FROM kitap ORDER BY basim_yili DESC; SQL
baslik basim_yili ----------------- ---------- Körlük 1995 Sessiz Ev 1983 Kum Kitabı 1975 Tehlikeli Oyunlar 1973 Tutunamayanlar 1972 Yaban 1932 Anayurt Oteli
Yön tersine döndüğünde boş değer de tarafını değiştirdi. Yeri sorguda sabitlemek için standart bir belirteç vardır.
sqlite3 kutuphane.db <<'SQL' .headers on .mode column SELECT baslik, basim_yili FROM kitap ORDER BY basim_yili NULLS LAST; SQL
baslik basim_yili ----------------- ---------- Yaban 1932 Tutunamayanlar 1972 Tehlikeli Oyunlar 1973 Kum Kitabı 1975 Sessiz Ev 1983 Körlük 1995 Anayurt Oteli
NULLS FIRST ve NULLS LAST belirteçleri artan sıralamada bile boş değerleri sona
alabilir. Desteği motora göre değişir; desteklenmeyen motorlarda aynı sonuç, boş olup
olmadığını sınayan bir ifadeyi birinci sıralama anahtarı yaparak elde edilir.
Harmanlama ve Metin Sırası
Metin sıralamasının sonucu harmanlamaya bağlıdır. Öntanımlı harmanlama karakterleri alfabetik değil, kodlarına göre karşılaştırıyorsa sonuç Türkçe alfabe sırasından ayrılır.
sqlite3 kutuphane.db <<'SQL' .headers on .mode column SELECT baslik FROM kitap ORDER BY baslik; SQL
baslik ----------------- Anayurt Oteli Kum Kitabı Körlük Sessiz Ev Tehlikeli Oyunlar Tutunamayanlar Yaban
Kum Kitabı, Körlük başlığından önce geldi. Türkçe alfabede ö harfi u harfinden
önce gelir; burada uygulanan karşılaştırma ise karakterlerin ikili gösterimini
karşılaştırdığı için u önce çıktı. Aynı etki yazar sütununda da görülür: Orhan Pamuk
ile Oğuz Atay arasındaki sıra da alfabetik değildir.
Bu bir hata değil, bir yapılandırma sonucudur. Dile duyarlı sıralama isteniyorsa sütuna ya da sorguya dile özgü bir harmanlama tanımlanır; hangi harmanlamaların bulunduğu ve nasıl adlandırıldığı motora göre değişir. Kullanıcıya gösterilen listelerde bu, göz ardı edildiğinde fark edilmesi güç bir kusurdur.
Çok Anahtarlı Sıralama
Birden çok anahtar virgülle ayrılır ve sırayla uygulanır: ilk anahtarda eşit olan satırlar ikinci anahtara göre sıralanır. Her anahtarın yönü ayrı yazılır.
sqlite3 kutuphane.db <<'SQL' .headers on .mode column SELECT baslik, yazar, basim_yili FROM kitap ORDER BY yazar, basim_yili DESC; SQL
baslik yazar basim_yili ----------------- ----------------- ---------- Kum Kitabı Jorge Luis Borges 1975 Körlük José Saramago 1995 Sessiz Ev Orhan Pamuk 1983 Tehlikeli Oyunlar Oğuz Atay 1973 Tutunamayanlar Oğuz Atay 1972 Yaban Yakup Kadri 1932 Anayurt Oteli Yusuf Atılgan
Aynı yazarın iki kitabı yeni basımdan eskiye sıralandı. DESC yalnız kendi anahtarına
uygulanır; yazar sütunu artan kaldı.
Sıralama anahtarı ifade de olabilir ve sonuç sütununun sıra numarası da yazılabilir.
sqlite3 kutuphane.db <<'SQL' .headers on .mode column SELECT baslik, basim_yili FROM kitap ORDER BY 2 DESC; SQL
baslik basim_yili ----------------- ---------- Körlük 1995 Sessiz Ev 1983 Kum Kitabı 1975 Tehlikeli Oyunlar 1973 Tutunamayanlar 1972 Yaban 1932 Anayurt Oteli
Sıra numarasıyla yazım kısa ama kırılgandır: sütun listesine bir sütun eklendiğinde sıralama sessizce başka bir sütuna kayar. Sütun adı ya da takma ad yazmak her zaman daha güvenlidir.
Belirlenimci Sıralama
ORDER BY yalnız yazıldığı anahtarlar üzerinde bir sıra kurar. Anahtarlarda eşit olan
satırların kendi aralarındaki sıra tanımsızdır ve motor planı değiştirdiğinde değişebilir.
Yukarıdaki sorguda yazar eşit olduğunda basım yılı ayırt ediciydi; ikisi de eşit olsaydı
sonuç çalıştırmadan çalıştırmaya farklılaşabilirdi.
Sonucun her çalıştırmada aynı olması gerekiyorsa — kütüğe yazılan raporlar, sayfalanmış
listeler, karşılaştırılan çıktılar — sıralama anahtarlarının sonuna benzersiz bir sütun
eklenir. Birincil anahtar bu iş için doğrudan uygundur. ORDER BY yazar, kitap_id yazımı,
yazarı aynı olan satırlar arasında bile tek bir sıra tanımlar.
Sınırlama
Sıralanmış bir sonucun yalnız ilk birkaç satırı isteniyorsa sınırlama yazılır. Standart yazım ile yaygın kısayol farklıdır ve bu, kursta ikinci kez karşılaşılan lehçe ayrımıdır.
sqlite3 kutuphane.db <<'SQL' .headers on .mode column SELECT baslik FROM kitap ORDER BY baslik FETCH FIRST 3 ROWS ONLY; SQL
Parse error near line 3: near "FETCH": syntax error
SELECT baslik FROM kitap ORDER BY baslik FETCH FIRST 3 ROWS ONLY;
error here ---^
Standart yazım OFFSET … ROWS FETCH FIRST … ROWS ONLY biçimindedir ve burada kullanılan
motor bunu tanımıyor. Motorun kabul ettiği yazım ise geniş bir kesimde ortak olan
kısayoldur.
sqlite3 kutuphane.db <<'SQL' .headers on .mode column SELECT baslik, basim_yili FROM kitap ORDER BY basim_yili DESC LIMIT 3; SQL
baslik basim_yili ---------- ---------- Körlük 1995 Sessiz Ev 1983 Kum Kitabı 1975
Atlanacak satır sayısı da belirtilebilir.
sqlite3 kutuphane.db <<'SQL' .headers on .mode column SELECT baslik, basim_yili FROM kitap ORDER BY basim_yili DESC LIMIT 3 OFFSET 3; SQL
baslik basim_yili ----------------- ---------- Tehlikeli Oyunlar 1973 Tutunamayanlar 1972 Yaban 1932
İki sorgu birlikte, üçer satırlık iki sayfa üretti. Sayfalama yazımının iki tuzağı vardır. Birincisi, sıralama yazılmadan sınırlama yazmak anlamsızdır: hangi satırların “ilk üç” olduğu tanımsız kalır ve iki ardışık sayfa aynı satırı iki kez gösterebilir. İkincisi, atlama sayısıyla sayfalama, sayfalar arasında veri değiştiğinde kayar — silinen bir satır sonraki sayfanın ilk satırını atlatır. Bu iki tuzağın ikincisi, İleri SQL kursunda anahtara dayalı sayfalama ile çözülür.
Atlama sayısının başarım maliyeti de sessizdir: motor atlanan satırları da üretip atmak zorundadır, dolayısıyla büyük atlama değerleri, sayfa numarası büyüdükçe yavaşlayan listeler üretir.
Özet
- Sıralama verinin değil sorgunun özelliğidir;
ORDER BYyazılmadan satır sırası tanımsızdır. - Boş değerlerin sıralamadaki yeri motora göre değişir;
NULLS FIRSTveNULLS LASTbelirteçleri yeri sabitler, ancak desteği de motora bağlıdır. - Metin sırası harmanlamaya bağlıdır; öntanımlı harmanlama Türkçe alfabe sırasını vermeyebilir.
- Çok anahtarlı sıralamada her anahtarın yönü ayrı yazılır ve anahtarlar sırayla uygulanır.
- Eşit anahtarlı satırların sırası tanımsızdır; belirlenimci sonuç için sıralamaya benzersiz bir sütun eklenir.
- Sınırlamanın standart yazımı ile yaygın kısayolu farklıdır; sıralamasız sınırlama anlamsız, atlamaya dayalı sayfalama ise veri değişiminde kaygandır.
Sonraki Adım
Son üç derste boş değer üç ayrı yerde karşımıza çıktı: hesaplanmış ifadeyi boşalttı, koşulun değillemesini eksik bıraktı, sıralamada motora bağlı bir yer aldı. Bunlar tek bir kuralın sonuçlarıdır. Sonraki ders o kuralı — bilinmeyen değerin üç değerli mantığını — kurar, boş değerle çalışan işlevleri tanıtır ve liste koşulunun değillemesinde ortaya çıkan tuzağı ölçer.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.