Bölüm 6: Subquery (Alt Sorgular)
SQL öğrenme serimin altıncı bölümünde subquery (alt sorgu) konusunu ele alacağım. Subquery, SQL’in en güçlü ve esnek özelliklerinden biridir. Bir sorgu içinde başka bir sorgu yazma yeteneği, karmaşık problemleri basit hale getirir.
Önceki bölümlerde WHERE, GROUP BY, JOIN gibi araçları öğrendik. Şimdi bu araçları iç içe kullanarak çok daha güçlü sorgular yazacağız.
Subquery Nedir?
Subquery (Alt Sorgu): Başka bir sorgu içinde yazılan bir sorgudur.
Get Ahmet Elbüz’s stories in your inbox
Join Medium for free to get updates from this writer.
Struktur:
SELECT ...
FROM ...
WHERE kolonadi = (SELECT kolonadi FROM ...)
↑
Bu kısım subqueryMantığı:
- İç sorgu (subquery) önce çalışır
- Sonucu dış sorguya verir
- Dış sorgu bu sonucu kullanır
Subquery Türleri
1. Skalar Subquery → Tek bir değer döndürür
WHERE ListPrice > (SELECT AVG(ListPrice) FROM Product)2. Multi-row Subquery → Birden fazla satır döndürür
WHERE Color IN (SELECT Color FROM Product WHERE ListPrice > 1000)3. Correlated Subquery → Dış sorguya bağlı olan
WHERE OrderQty > (SELECT AVG(OrderQty) FROM OrderDetail od2 WHERE od2.ProductID = od1.ProductID)Bu yazıda Skalar Subquery’lere odaklanacağız.
Adım 1: En Pahalı Ürünün Rengi
Problem: En pahalı fiyata sahip ürünün rengiyle aynı renge sahip olan tüm ürünleri bulun.
Normal Düşünüş (2 Sorgu):
-- Adım 1: En pahalı ürünün rengi nedir?
SELECT TOP 1 Color
FROM Production.Product
ORDER BY ListPrice DESC
-- Sonuç: Red (örneğin)
-- Adım 2: Red rengindeki tüm ürünler
SELECT *
FROM Production.Product
WHERE Color = 'Red'Subquery ile (1 Sorgu):
SELECT *
FROM Production.Product
WHERE Color = (SELECT TOP 1 Color
FROM Production.Product
ORDER BY ListPrice DESC)Ne Oldu?
- İç sorgu:
SELECT TOP 1 Color FROM Product ORDER BY ListPrice DESC→ En pahalı ürünün rengi (örn: Red) - Dış sorgu:
WHERE Color = Redgibi davranır - Sonuç: Red rengindeki tüm ürünler gelir
Avantajları:
- Tek sorguda sonuç
- En pahalı ürünün rengi değişse otomatik güncellenir
- Daha okunabilir ve bakım yapılabilir
Adım 2: Maksimum Tarih ile Subquery
Problem: En son verilen sipariş ile aynı tarihte verilen tüm siparişleri bulun.
Subquery Çözüm:
SELECT *
FROM Sales.SalesOrderHeader
WHERE OrderDate = (SELECT MAX(OrderDate)
FROM Sales.SalesOrderHeader)Açıklama:
İç Sorgu: MAX(OrderDate) → En yeni tarih (örn: 2014-06-30)
Dış Sorgu: WHERE OrderDate = 2014-06-30
Sonuç: Bu tarihte verilen tüm siparişlerMantık: Eğer bir gün içinde 5 sipariş varsa, 5 satır gelir.
Adım 3: Ortalama ile Subquery
Problem: Fiyatı ortalama fiyattan yüksek olan ürünleri bulun.m
SELECT Name, ListPrice
FROM Production.Product
WHERE ListPrice > (SELECT AVG(ListPrice) FROM Production.Product)
ORDER BY ListPrice DESCÇalışma Sırası:
1. İç sorgu: SELECT AVG(ListPrice) → Ortalama fiyat (örn: 437.5)
2. Dış sorgu: WHERE ListPrice > 437.5
3. Sonuç: 437.5'ten daha pahalı tüm ürünlerÖrnek Sonuç:
Name ListPrice
------------------- ---------
Road-150 Red 1098.77
HL Mountain Frame 1349.60
HL Touring Frame 1500.00
...Subquery vs JOIN: Hangisini Kullanmalı?
Aynı Problemi İki Şekilde Çöz:
Subquery ile:
SELECT p1.Name, p1.ListPrice
FROM Production.Product p1
WHERE ListPrice > (SELECT AVG(ListPrice) FROM Production.Product)JOIN ile:
SELECT p1.Name, p1.ListPrice
FROM Production.Product p1
WHERE ListPrice > (SELECT AVG(ListPrice) FROM Production.Product)(Bu örnekte aslında JOIN gerekmiyor, ama daha karmaşık senaryolarda kullanılır)
Subquery’nin Gücü: Neden Kullanırız?
1. Dinamik Filtreler
-- Statik (kötü):
WHERE Color = 'Red' -- Red'i elle yazdık
-- Dinamik (iyi):
WHERE Color = (SELECT TOP 1 Color FROM Product ORDER BY ListPrice DESC)
-- En pahalı ürünün rengi ne olursa olsun otomatik bulur2. Aggregate’ler ile Filtrele
-- WHERE'de aggregate kullanamıyoruz:
WHERE AVG(ListPrice) > 500 -- ❌ HATA!
-- Subquery ile çözüm:
WHERE ListPrice > (SELECT AVG(ListPrice) FROM Product) -- ✅3. Karmaşık Mantık
-- "En pahalı ürünün kategorisindeki tüm ürünler"
SELECT *
FROM Product
WHERE CategoryID = (SELECT CategoryID
FROM Product
WHERE Price = (SELECT MAX(Price) FROM Product))Subquery Yazım Kuralları
1. Parantezler Zorunlu
-- ❌ HATA
WHERE ListPrice > SELECT AVG(ListPrice) FROM Product
-- ✅ DOĞRU
WHERE ListPrice > (SELECT AVG(ListPrice) FROM Product)2. Skalar Subquery Tek Değer Döndürmeli
-- ❌ HATA - 504 satır dönecek!
WHERE ListPrice > (SELECT ListPrice FROM Product)
-- ✅ DOĞRU - 1 satır dönecek
WHERE ListPrice > (SELECT AVG(ListPrice) FROM Product)3. NULL Kontrolü
-- Subquery NULL döndürürse sonuç NULL olur
WHERE OrderDate = (SELECT MAX(OrderDate) FROM SalesOrderHeader WHERE 1=0)
-- Bu NULL döner, WHERE NULL = NULL hiçbir satırı seçmez!Pratik Örnekler
Örnek 1: En Çok Sipariş Veren Müşteri ile Aynı Bölgede Siparişler
SELECT *
FROM Sales.SalesOrderHeader
WHERE TerritoryID = (SELECT TOP 1 TerritoryID
FROM Sales.SalesOrderHeader
GROUP BY TerritoryID
ORDER BY COUNT(*) DESC)Örnek 2: Ortalamanın Üstünde Kalitede Ürünler
SELECT Name, ListPrice
FROM Production.Product
WHERE ListPrice > (SELECT AVG(ListPrice) FROM Production.Product)
AND ListPrice < (SELECT MAX(ListPrice) FROM Production.Product)
ORDER BY ListPrice DESCÖrnek 3: Hiç Sipariş Almamış Ürünler
SELECT *
FROM Production.Product
WHERE ProductID NOT IN (SELECT DISTINCT ProductID
FROM Sales.SalesOrderDetail)Subquery vs GROUP BY + HAVING
Aynı sonucu iki şekilde elde edebiliriz:
Subquery ile:
SELECT Name, ListPrice
FROM Product
WHERE ListPrice > (SELECT AVG(ListPrice) FROM Product)GROUP BY + HAVING ile:
SELECT Name, ListPrice
FROM Product
GROUP BY Name, ListPrice
HAVING ListPrice > (SELECT AVG(ListPrice) FROM Product)Ne Zaman Hangisini Kullan:
- Subquery: Basit filtreler için
- GROUP BY: Gruplama ve aggregate’ler için
Performans İpuçları 💡
1. Subquery Kaç Kez Çalışır?
-- Bu subquery her satır için çalışır!
SELECT *
FROM Product p1
WHERE ListPrice > (SELECT AVG(ListPrice) FROM Product p2)
-- Çalışma sayısı: 504 (ürün sayısı kadar)
-- ❌ Yavaş (ama çalışır)2. Hızlandırma: Alias ile
-- Subquery'yi önce tanımla
DECLARE @AvgPrice DECIMAL = (SELECT AVG(ListPrice) FROM Product)
SELECT *
FROM Product
WHERE ListPrice > @AvgPrice
-- ✅ Daha hızlıÖzet
Bu bölümde öğrendiklerimiz:
- ✅ Subquery nedir → Sorgu içinde sorgu
- ✅ Skalar Subquery → Tek değer döndürür
- ✅ WHERE içinde Subquery → Dinamik filtreler
- ✅ MAX(), AVG() ile Subquery → Aggregate’ler kullanma
- ✅ Subquery vs JOIN → Ne zaman hangisini kullan
- ✅ Parantezler zorunlu → Syntax kuralları
Subquery’ler başta karmaşık görünebilir, ama pratikle çok güçlü bir araç haline gelir. Her gün bir subquery yazarak becerinizi geliştirin!
Sorularınız varsa yorumlarda buluşalım! 🚀








