İçeriğe geç
academia.sh

Ders 02 / 18

SELECT Yapısı

Sütun listesinin ne olduğu, takma adlar, hesaplanmış ifadeler, yinelenen satırların elenmesi ve yan tümcelerin yazım sırası ile değerlendirme sırası arasındaki fark.

İçindekiler

Önceki ders SQL’in beş deyim ailesini ayırdı ve sorgulama ailesinin tek bir deyimden — SELECT — oluştuğunu söyledi. Bu deyim örnek olarak bir kez kullanıldı: iki sütun, bir tablo, bir koşul. Oysa SELECT yan tümcesine yazılabilecek şey tablo sütunlarının adlarıyla sınırlı değildir.

Bu ders sütun listesinin ne kabul ettiğini kurar. Bir sorgunun ürettiği sonuç yeni bir bağıntıdır; sütunları tablodaki sütunlarla aynı olmak zorunda değildir. Adları değişebilir, sayıları değişebilir, hiç var olmayan bir sütun hesaplanarak eklenebilir.

Aşağıdaki blok kurs boyunca kullanılan şemayı ve örnek veriyi kurar. Bu 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

Yıldız ve Açık Liste

En kısa sorgu, tablonun bütün sütunlarını ister.

sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT * FROM sube;
SQL
sube_id  ad            sehir   
-------  ------------  --------
1        Merkez        Ankara  
2        Bahçelievler  Ankara  
3        Kadıköy       İstanbul
4        Konak         İzmir   

Yıldız, “tablonun o anki bütün sütunları” anlamına gelir. Keşif sırasında yararlıdır ve kalıcı kodda üç ayrı soruna yol açar. Birincisi, şemaya sonradan sütun eklendiğinde sonuç kümesinin sütun sayısı sessizce değişir; sütunları sırayla okuyan çağıran taraf bozulur. İkincisi, gerekmeyen sütunlar da okunur — geniş bir metin sütunu için bu, gereksiz disk ve ağ trafiği demektir. Üçüncüsü, sorguyu okuyan kişi hangi sütunlara gerçekten ihtiyaç duyulduğunu göremez.

Açık liste bu üç sorunu birden ortadan kaldırır.

sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT baslik, yazar FROM kitap;
SQL
baslik             yazar            
-----------------  -----------------
Körlük             José Saramago    
Tutunamayanlar     Oğuz Atay        
Kum Kitabı         Jorge Luis Borges
Yaban              Yakup Kadri      
Sessiz Ev          Orhan Pamuk      
Anayurt Oteli      Yusuf Atılgan    
Tehlikeli Oyunlar  Oğuz Atay        

Sütun listesindeki sıra sonuçtaki sıradır. Tablodaki fiziksel sıra bağlayıcı değildir.

Takma Adlar

Sonuç kümesindeki bir sütunun adı AS ile değiştirilebilir. Buna takma ad (alias) denir.

sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT baslik AS kitap_adi, yazar AS yazan FROM kitap WHERE sube_id = 1;
SQL
kitap_adi       yazan        
--------------  -------------
Körlük          José Saramago
Tutunamayanlar  Oğuz Atay    

Takma ad iki işe yarar. Sütuna anlamlı bir ad verir — özellikle hesaplanmış ifadelerde, çünkü hesaplanmış bir sütunun öntanımlı adı motora göre değişen bir dizedir. İkincisi, birleştirmelerde aynı adı taşıyan iki sütunu ayırt etmeyi sağlar; bu, ikinci konunun konusudur.

AS sözcüğü çoğu motorda isteğe bağlıdır — baslik kitap_adi yazımı da çalışır. Yine de AS yazmak, sütun listesinde unutulmuş bir virgülün sessizce takma ada dönüşmesini önler. SELECT baslik yazar FROM kitap deyimi hata vermez; iki sütun yerine, adı yazar olan tek bir sütun döndürür.

Hesaplanmış İfadeler

Sütun listesine sütun adı değil, ifade yazılabilir. İfade satır başına değerlendirilir ve sonuç kümesinde yeni bir sütun olarak görünür.

Metin birleştirme standartta || işleciyle yazılır.

sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT ad || ' ' || soyad AS tam_ad, kayit_tarihi FROM uye;
SQL
tam_ad         kayit_tarihi
-------------  ------------
Ayşe Demir     2023-02-14  
Mehmet Kaya    2023-05-30  
Zeynep Arslan  2024-01-09  
Emre Yıldız    2024-03-22  
Selin Aydın    2024-11-05  
Burak Şahin    2025-01-18  

Birleştirme işlecinin yazımı motora göre değişir: bazı motorlar || yerine ya da onunla birlikte bir birleştirme işlevi sunar, bazılarında || bambaşka bir anlam taşır. Taşınabilir olması gereken sorgularda bu, ilk kontrol edilecek noktalardandır.

Aritmetik ifadeler de aynı biçimde yazılır. Aşağıdaki sorgu basım yılından on yıllık dilimi hesaplar.

sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT baslik, basim_yili, (basim_yili / 10) * 10 AS on_yil FROM kitap;
SQL
baslik             basim_yili  on_yil
-----------------  ----------  ------
Körlük             1995        1990  
Tutunamayanlar     1972        1970  
Kum Kitabı         1975        1970  
Yaban              1932        1930  
Sessiz Ev          1983        1980  
Anayurt Oteli                        
Tehlikeli Oyunlar  1973        1970  

İki gözlem var. Birincisi, iki tam sayının bölümünün tam sayı olarak mı yoksa ondalık olarak mı değerlendirileceği motora göre değişir; burada tam sayı bölmesi uygulandığı için 1995 / 10 işlemi 199 verdi. Taşınabilir yazım, bölmeden önce tipi açıkça belirlemektir.

İkincisi, Anayurt Oteli satırında on_yil sütunu boş. Basım yılı bilinmediği için ifadenin sonucu da bilinmiyor: boş değeri içeren aritmetik ifade boş değer üretir. Bu davranış beşinci dersin tamamını dolduracak kadar sonuç doğurur.

Yinelenen Satırların Elenmesi

SELECT sonucu bir çoklu kümedir: aynı satır birden çok kez görünebilir. DISTINCT anahtar sözcüğü yinelenen satırları eler.

sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT DISTINCT yazar FROM kitap;
SQL
yazar            
-----------------
José Saramago    
Oğuz Atay        
Jorge Luis Borges
Yakup Kadri      
Orhan Pamuk      
Yusuf Atılgan    

Yedi kitap var ama altı yazar döndü: aynı yazarın iki kitabı tek satıra indi.

DISTINCT sütuna değil, sonuç satırının tamamına uygulanır. SELECT DISTINCT yazar, baslik yazımı yazarları değil, yazar–başlık çiftlerini tekilleştirir; kitap başlıkları farklı olduğu için hiçbir satır elenmez. Bu, DISTINCT ile en sık yapılan yanlıştır: bir sütunu tekilleştirmek isterken sonuç kümesine ikinci bir sütun eklendiğinde eleme etkisiz kalır.

Çıktıdaki sıraya güvenilmemelidir. Sıralama belirtilmeyen bir sorgunun satır sırası tanımsızdır; motor tekilleştirmeyi hangi yöntemle yaparsa sıra ona göre çıkar. Sıra gerektiğinde dördüncü dersteki sıralama yan tümcesi yazılır.

Değerlendirme Sırası

Yazım sırası SELECT, FROM, WHERE biçimindedir; anlam sırası ise FROM, WHERE, SELECT biçimindedir. Motor önce hangi tablodan okuyacağını belirler, sonra satırları süzer, en son sütun listesini hesaplar.

Bunun ölçülebilir bir sonucu var: SELECT yan tümcesinde tanımlanan bir takma ad, kendisinden önce değerlendirilen WHERE yan tümcesinde standarda göre görünür değildir.

sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT ad || ' ' || soyad AS tam_ad FROM uye WHERE tam_ad = 'Ayşe Demir';
SQL
tam_ad    
----------
Ayşe Demir

Sorgu burada çalıştı. Ancak bu, standart bir davranış değil, kullanılan motorun sağladığı bir gevşemedir; aynı sorgu başka bir motorda “böyle bir sütun yok” hatası verebilir. Davranış motora göre değişir. Taşınabilir yazım, ifadenin WHERE içinde tekrar edilmesidir:

sqlite3 kutuphane.db <<'SQL'
.headers on
.mode column
SELECT ad || ' ' || soyad AS tam_ad FROM uye WHERE ad || ' ' || soyad = 'Ayşe Demir';
SQL
tam_ad    
----------
Ayşe Demir

İfadenin iki kez yazılması motorun onu iki kez hesaplayacağı anlamına gelmez; bildirimsel dilde tekrar, plana değil yazıma aittir.

Özet

  • Sonuç kümesi yeni bir bağıntıdır; sütunları tablonun sütunlarıyla aynı olmak zorunda değildir.
  • Yıldız yazımı keşif için uygundur, kalıcı sorgularda şema değişikliğine kırılgan ve gereksiz veri okur.
  • Takma ad sütuna ad verir; AS yazmak, unutulmuş virgülün sessizce takma ada dönüşmesini önler.
  • Sütun listesine ifade yazılabilir; boş değer içeren ifade boş değer üretir.
  • DISTINCT tek bir sütuna değil, sonuç satırının tamamına uygulanır.
  • Yazım sırası ile değerlendirme sırası ayrıdır; SELECT içindeki takma adın WHERE içinde görünürlüğü motora göre değişir.

Sonraki Adım

Bu dersteki WHERE yan tümceleri tek bir eşitlikten ibaretti. Oysa süzme, sorgunun sonucunu en çok belirleyen yan tümcedir: karşılaştırma işleçleri, mantıksal bağlaçlar, aralık ve liste denetimleri, metin örüntüsü eşleme. Sonraki ders koşul yazımını bütün biçimleriyle kurar ve örüntü eşlemenin büyük/küçük harf davranışının neden motora bağlı olduğunu gösterir.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat