SQL veritabanlarında karmaşık veri manipülasyonları ve sorgulamaları için güçlü bir araç olan alt sorgular (subquery) ve iç içe sorgular, temel SQL komutlarının ötesinde esneklik sunar. Bu yapılar, tek bir sorgu içinde birden fazla sorguyu birleştirerek daha spesifik ve detaylı sonuçlar elde etmemizi sağlar. Veri analizi, raporlama ve dinamik filtreleme gibi birçok senaryoda vazgeçilmez bir role sahiptirler, SQL yetkinliğinizi derinleştirmenin anahtarıdır.
Alt Sorgu (Subquery) Nedir?
Alt sorgu, bir SQL sorgusunun başka bir SQL sorgusunun içine gömülmesiyle oluşan yapıdır. Ana sorgu tarafından kullanılan bir değer, satır seti veya tablo seti döndürür. Genellikle parantez içine alınır ve ana sorgudan önce yürütülür (korele alt sorgular hariç). Alt sorgular, belirli bir koşulu karşılayan verileri filtrelemek, başka bir tablodan türetilmiş değerlerle karşılaştırmak veya dinamik olarak oluşturulan veri setlerini kullanmak için kullanılır.
Alt Sorguların Kullanım Alanları ve Türleri
Alt sorgular, SELECT, FROM, WHERE, HAVING cümlelerinde ve hatta INSERT, UPDATE, DELETE ifadelerinde kullanılabilir. Temel olarak üç ana türe ayrılırlar:
1. Skaler Alt Sorgular (Scalar Subqueries)
Tek bir değer (tek bir satır, tek bir sütun) döndüren alt sorgulardır. Genellikle SELECT veya WHERE cümlelerinde kullanılırlar.
Örnek: Belirli bir ürün kategorisindeki en yüksek fiyatı bulmak ve bu fiyata sahip ürünleri listelemek.
SELECT UrunAdi, Fiyat
FROM Urunler
WHERE Fiyat = (SELECT MAX(Fiyat) FROM Urunler WHERE KategoriID = 1);
Bu örnekte, (SELECT MAX(Fiyat) FROM Urunler WHERE KategoriID = 1) kısmı skaler bir alt sorgudur ve KategoriID’si 1 olan ürünlerin en yüksek fiyatını döndürür.
2. Satır Alt Sorguları (Row Subqueries)
Tek bir satır ancak birden fazla sütun döndüren alt sorgulardır. Genellikle WHERE veya HAVING cümlelerinde, karşılaştırma operatörleriyle (=, >, <) birlikte kullanılırlar.
Örnek: En yüksek fiyata sahip ürünün hem fiyatını hem de kategori ID’sini bulmak.
SELECT UrunAdi, Fiyat, KategoriID
FROM Urunler
WHERE (Fiyat, KategoriID) = (SELECT MAX(Fiyat), KategoriID FROM Urunler GROUP BY KategoriID ORDER BY MAX(Fiyat) DESC LIMIT 1);
Bu örnekte, ana sorgu sadece tek bir (Fiyat, KategoriID) ikilisi ile eşleşen bir ürünü döndürecektir. LIMIT 1 kullanımı, alt sorgunun tek bir satır döndürmesini sağlar.
3. Tablo Alt Sorguları (Table Subqueries)
Birden fazla satır ve birden fazla sütun döndüren alt sorgulardır. Genellikle FROM cümlesinde, türetilmiş bir tablo olarak kullanılırlar. Bunlara “İç İçe Sorgular” da denir ve geçici bir tablo gibi davranırlar.
Örnek: Her kategorideki ortalama ürün fiyatını bulup, bu ortalamadan daha pahalı olan ürünleri listelemek.
SELECT U.UrunAdi, U.Fiyat, K.KategoriAdi, OrtFiyatlar.OrtalamaFiyat
FROM Urunler U
INNER JOIN Kategoriler K ON U.KategoriID = K.KategoriID
INNER JOIN (
SELECT KategoriID, AVG(Fiyat) AS OrtalamaFiyat
FROM Urunler
GROUP BY KategoriID
) AS OrtFiyatlar ON U.KategoriID = OrtFiyatlar.KategoriID
WHERE U.Fiyat > OrtFiyatlar.OrtalamaFiyat;
Bu örnekte, (SELECT KategoriID, AVG(Fiyat) AS OrtalamaFiyat FROM Urunler GROUP BY KategoriID) kısmı tablo alt sorgusudur ve her kategori için ortalama fiyatı hesaplayan bir türetilmiş tablo oluşturur. Bu türetilmiş tablo daha sonra ana sorgu ile birleştirilir.
Alt Sorguların Diğer Kullanım Senaryoları
WHERE ve HAVING ile Birlikte Kullanım:
IN,NOT IN,EXISTS,NOT EXISTSoperatörleriyle sıkça kullanılırlar.
IN Örneği: Belirli bir şehirdeki müşterilerin verdiği siparişleri listele.
SELECT SiparisID, MusteriID, SiparisTarihi
FROM Siparisler
WHERE MusteriID IN (SELECT MusteriID FROM Musteriler WHERE Sehir = 'Ankara');
EXISTS Örneği: Hiç sipariş vermemiş müşterileri bul (Korele alt sorgu örneği).
SELECT MusteriAdi, Eposta
FROM Musteriler M
WHERE NOT EXISTS (SELECT 1 FROM Siparisler S WHERE S.MusteriID = M.MusteriID);
Burada, EXISTS ana sorgunun her satırı için iç sorguyu çalıştırır. Eğer iç sorgu herhangi bir sonuç döndürürse (EXISTS true olur), ana sorgu o satırı filtrelemez.
Korele (Correlated) Alt Sorgular:
Bu tür alt sorgular, dış (ana) sorgunun her satırı için bir kez çalışır ve dış sorgudan bir değer alır. Yukarıdaki EXISTS örneği buna güzel bir örnektir. Korele alt sorgular genellikle NOT EXISTS veya EXISTS ile birlikte kullanılır ve performansı etkileyebilirler, bu yüzden dikkatli kullanılmalıdırlar.
Örnek: Kendi kategorisindeki ortalama fiyattan daha pahalı olan ürünleri listele.
SELECT UrunAdi, Fiyat, KategoriID
FROM Urunler U1
WHERE Fiyat > (SELECT AVG(Fiyat) FROM Urunler U2 WHERE U2.KategoriID = U1.KategoriID);
Burada, U1.KategoriID ana sorgudan gelen bir değerdir ve iç sorgunun her çalışmasında değişir.
INSERT, UPDATE, DELETE ile Kullanım:
Alt sorgular, veri manipülasyonu (DML) ifadelerinde de dinamik değerler veya koşullar sağlamak için kullanılabilir.
INSERT Örneği: Bir tablodan seçilen verileri başka bir tabloya ekle.
INSERT INTO ArsivUrunler (UrunAdi, Fiyat, EklenmeTarihi)
SELECT UrunAdi, Fiyat, GETDATE() -- veya CURRENT_TIMESTAMP
FROM Urunler
WHERE StokAdedi = 0;
UPDATE Örneği: Belirli bir kategorideki ürün fiyatlarını, o kategorinin ortalama fiyatının %10 üzerine çıkar.
UPDATE Urunler U1
SET Fiyat = (SELECT AVG(Fiyat) * 1.10 FROM Urunler U2 WHERE U2.KategoriID = U1.KategoriID)
WHERE KategoriID IN (SELECT KategoriID FROM Kategoriler WHERE KategoriAdi = 'Elektronik');
Alt Sorguların Avantajları ve Dezavantajları
Avantajlar:
- Kod Okunabilirliği: Karmaşık birleştirme (JOIN) işlemleri yerine, daha mantıksal ve okunabilir bir yol sunabilirler.
- Modülerlik: Sorguyu daha küçük, yönetilebilir parçalara ayırır.
- Esneklik: Neredeyse her SQL cümlesinde kullanılabilir ve çok çeşitli senaryolara uyum sağlar.
- Dinamik Filtreleme: Statik değerler yerine dinamik olarak hesaplanan değerlerle filtreleme imkanı sunar.
Dezavantajlar:
- Performans: Özellikle korele alt sorgular veya çok fazla iç içe geçmiş alt sorgular, performansı olumsuz etkileyebilir. Her dış satır için yeniden çalıştırılma maliyeti olabilir.
- Anlaşılabilirlik (Yanlış Kullanımda): Aşırı iç içe geçmiş veya kötü yazılmış alt sorgular, okunabilirliği ve hata ayıklamayı zorlaştırabilir.
- Alternatifler: Bazı durumlarda
JOINişlemleri, CTE’ler (Common Table Expressions) veya türetilmiş tablolar, alt sorgulara göre daha performanslı veya okunabilir çözümler sunabilir.
Ne Zaman ve Nasıl Kullanmalı?
Alt sorgular, bir değeri veya bir dizi değeri başka bir sorgunun sonucu olarak dinamik olarak belirlemeniz gerektiğinde idealdir. Genellikle, bir tablodaki veriyi aynı tablodaki veya başka bir tablodaki diğer verilerle karşılaştırmanız gerektiğinde tercih edilir. Performans endişesi taşıdığınızda, özellikle büyük veri setlerinde, alt sorguyu birleştirme (JOIN) işlemine dönüştürmenin mümkün olup olmadığını veya CTE kullanıp kullanamayacağınızı düşünmek faydalı olacaktır.
Sonuç
SQL’deki alt sorgular ve iç içe sorgular, veri manipülasyonunda ve analizinde esneklik ile güç sağlayan temel yapılardır. Skaler, satır ve tablo alt sorguları gibi çeşitli türleriyle, karmaşık iş mantığını tek bir sorgu içinde ifade etmenizi mümkün kılarlar. Doğru anlaşıldığında ve uygun şekilde kullanıldığında, SQL sorgularınızın okunabilirliğini artırırken, dinamik ve güçlü filtreleme yetenekleri sunarlar. Performans üzerindeki potansiyel etkileri nedeniyle dikkatli optimizasyon ve alternatiflerle değerlendirilmelidirler.