Sitemap

Bölüm 6: Subquery (Alt Sorgular)

4 min readMay 28, 2026

--

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 subquery

Mantığı:

  1. İç sorgu (subquery) önce çalışır
  2. Sonucu dış sorguya verir
  3. Dış sorgu bu sonucu kullanır
Press enter or click to view image in full size

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?

  1. İç sorgu: SELECT TOP 1 Color FROM Product ORDER BY ListPrice DESC → En pahalı ürünün rengi (örn: Red)
  2. Dış sorgu: WHERE Color = Red gibi davranır
  3. 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şler

Mantı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 bulur

2. 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! 🚀

--

--