Tüm yazılarPerSight Ekibi · Son güncelleme: 23 Temmuz 2026 · 8 dk okuma

SQL Alt Sorgu (Subquery): Ne Zaman, Nasıl ve NOT IN Tuzağı

Sorgu içinde sorgu: skaler alt sorgu, IN, EXISTS ve ilişkili (correlated) alt sorgular. NOT IN'in NULL ile neden boş sonuç döndürdüğü ve JOIN'e göre ne zaman tercih edileceği.

Alt sorgu, adı üstünde, bir sorgunun içinde çalışan başka bir sorgudur. "Ortalamanın üzerinde fiyatlı ürünler" ya da "hiç sipariş vermemiş müşteriler" gibi, önce bir ara sonucu hesaplayıp sonra ona göre süzmeniz gereken her yerde işe yarar. Birkaç türü ve bir de meşhur bir tuzağı var; onları görelim.

Skaler alt sorgu: tek bir değer üreten sorgu

En basit tür, tek bir değer (bir satır, bir kolon) döndürür ve bu değeri bir karşılaştırmada kullanırsınız. Ortalama fiyatın üzerindeki ürünler:

SELECT ad, fiyat
FROM urunler
WHERE fiyat > (SELECT AVG(fiyat) FROM urunler);

Parantez içindeki sorgu önce çalışır, ortalamayı bulur; dıştaki sorgu her ürünü bu ortalamayla kıyaslar. Skaler alt sorgu SELECT satırında da kullanılabilir; örneğin her ürünün yanına toplam ortalamayı yazdırmak gibi.

IN ve EXISTS: "şu listede var mı?"

"Bu yıl sipariş vermiş müşteriler" gibi bir soruda, bir listeye üyelik ararsınız. İki yaygın yol vardır: IN bir değer listesiyle, EXISTS ise bir satırın varlığıyla eşleşir:

-- IN ile
SELECT ad
FROM musteriler
WHERE id IN (
  SELECT musteri_id
  FROM siparisler
  WHERE tarih >= DATE '2026-01-01'
);

-- EXISTS ile (çoğu zaman daha verimli)
SELECT m.ad
FROM musteriler m
WHERE EXISTS (
  SELECT 1
  FROM siparisler s
  WHERE s.musteri_id = m.id
    AND s.tarih >= DATE '2026-01-01'
);
SQL Server DATE literalini tanımaz; orada tarihi düz metin (2026-01-01) olarak yazın.

EXISTS ilk eşleşmeyi bulduğu anda durur ve genelde büyük tablolarda daha hızlıdır. IN ise okunması daha kolaydır. Küçük listelerde fark önemsizdir; büyük veri kümelerinde EXISTS'i tercih edin.

Dikkat: NOT IN ve NULL tuzağı

Bu, tecrübeli kişileri bile yakalar. Alt sorgunun döndürdüğü listede tek bir NULL varsa, NOT IN hiçbir satır döndürmez; hata da vermez, sessizce boş sonuç verir. Nedeni, NULL ile karşılaştırmanın "bilinmeyen" sonuç üretmesidir. "Hiç sipariş vermemiş müşteriler"i NOT IN ile ararken bu tuzağa düşmemek için NOT EXISTS kullanın:

SELECT m.ad
FROM musteriler m
WHERE NOT EXISTS (
  SELECT 1
  FROM siparisler s
  WHERE s.musteri_id = m.id
);
NULL'a karşı dayanıklı; NOT IN yerine bunu tercih edin.

İlişkili (correlated) alt sorgu nedir?

Yukarıdaki EXISTS örneklerinde alt sorgu, dıştaki satıra (m.id) atıfta bulunuyor. Buna ilişkili alt sorgu denir: her dış satır için bir kez çalışır. Güçlüdür ama dikkatli kullanılmazsa yavaşlayabilir; çoğu durumda aynı sonucu bir JOIN ya da pencere fonksiyonuyla daha hızlı alırsınız.

Sık sorulan sorular

Alt sorgu mu JOIN mi daha hızlı?
Modern veritabanları çoğu alt sorguyu içeride JOIN'e benzer biçimde optimize eder, bu yüzden fark genellikle küçüktür. Okunabilirliğe göre seçin: başka tablodan kolon göstereceksen JOIN, yalnızca üyelik/varlık süzeceksen IN/EXISTS. Kararsızsanız ikisini de yazıp sorgu planına bakın.
Neden NOT IN bazen boş sonuç veriyor?
Alt sorgunun döndürdüğü listede NULL varsa NOT IN'in mantığı "bilinmeyen"e döner ve hiçbir satır geçmez. Çözüm: NOT EXISTS kullanın ya da alt sorguda NULL'ları eleyin (WHERE kolon IS NOT NULL).
FROM içinde alt sorgu (türetilmiş tablo) kullanabilir miyim?
Evet. FROM (SELECT ...) t şeklinde bir alt sorguyu geçici bir tablo gibi kullanabilirsiniz; top-N per group kalıbında tam da bunu yaparız. Okunabilirlik için aynı işi CTE (WITH ...) ile de yazabilirsiniz.
Alt sorgu birden fazla satır döndürürse ne olur?
Skaler beklenen bir yerde (örneğin = ile) alt sorgu birden çok satır döndürürse veritabanı hata verir. Böyle durumlarda IN kullanın ya da alt sorguyu tek satıra indirgeyin (örneğin MAX, LIMIT 1 ile).

IN mi EXISTS mi diye tartmak istemiyorsanız soruyu olduğu gibi PerSight'a bırakın. "Hiç sipariş vermemiş müşterileri göster" yazın; uygun kalıbı seçer, kurduğu SQL'i Türkçe açıklamasıyla önünüze koyar.

Kaynaklar