Correlated vs Non-Correlated Subquery
Giriş — Bağımlı ve Bağımsız Alt Sorgular
Subquery'ler ikiye ayrılır: dış sorgudan bağımsız çalışanlar (non-correlated) ve dış sorgunun her satırına bağlı çalışanlar (correlated). Bu fark hem mantık hem performans açısından kritiktir.
Non-Correlated (Bağımsız) Subquery
Dış sorgudan bağımsız, tek başına çalıştırılabilir:
-- Subquery tek başına çalışır — dış sorgudan bağımsız
SELECT product_name, price
FROM products
WHERE price > (SELECT AVG(price) FROM products);
-- (SELECT AVG(price) FROM products) tek başına çalışır: 13009.99
-- BİR KERE çalışır, sonucu cache'lenirCorrelated (Bağımlı) Subquery
Dış sorgunun her satırı için tekrar çalışır:
-- Her ürünün kendi kategorisindeki ortalamadan pahalı olup olmadığı
SELECT p.product_name, p.price, p.category_id
FROM products p
WHERE p.price > (
SELECT AVG(p2.price)
FROM products p2
WHERE p2.category_id = p.category_id -- ← Dış sorgudaki p'ye referans!
);
-- Her ürün için subquery yeniden çalışır (farklı category_id ile)Nasıl çalışır:
Dış sorgu ilk satırı alır (product_id = 1, category_id = 2)
Subquery çalışır:
AVG(price) WHERE category_id = 2→ 36999.99Karşılaştır: 54999.99 > 36999.99? Evet → dahil et
İkinci satır... (tekrar)
Karşılaştırma
| Özellik | Non-Correlated | Correlated |
|---|---|---|
| Bağımlılık | Bağımsız | Dış sorguya bağımlı |
| Çalışma sayısı | 1 kere | Her dış satır için 1 kere |
| Performans | ✅ Genellikle hızlı | ⚠️ Yavaş olabilir |
| Kullanım | Sabit karşılaştırma | Satır bazlı karşılaştırma |
Correlated Subquery Örnekleri
-- Her kategorideki en pahalı ürün
SELECT p.product_name, p.price, p.category_id
FROM products p
WHERE p.price = (
SELECT MAX(p2.price) FROM products p2 WHERE p2.category_id = p.category_id
);
-- Her müşterinin son siparişi
SELECT o.customer_id, o.order_id, o.order_date, o.total_amount
FROM orders o
WHERE o.order_date = (
SELECT MAX(o2.order_date) FROM orders o2 WHERE o2.customer_id = o.customer_id
);
-- Ortalamanın üstünde sipariş veren müşteriler (correlated)
SELECT c.first_name, c.last_name
FROM customers c
WHERE (
SELECT AVG(o.total_amount) FROM orders o WHERE o.customer_id = c.customer_id
) > (SELECT AVG(total_amount) FROM orders);Correlated Subquery → JOIN Dönüşümü
Correlated subquery'leri JOIN ile yeniden yazmak genellikle daha performanslıdır:
-- Correlated subquery (yavaş olabilir)
SELECT p.product_name, p.price
FROM products p
WHERE p.price = (
SELECT MAX(p2.price) FROM products p2 WHERE p2.category_id = p.category_id
);
-- JOIN ile (genellikle daha hızlı)
SELECT p.product_name, p.price
FROM products p
INNER JOIN (
SELECT category_id, MAX(price) AS max_price
FROM products GROUP BY category_id
) AS cat_max ON p.category_id = cat_max.category_id AND p.price = cat_max.max_price;SELECT'te Correlated Subquery
-- Her müşterinin sipariş sayısı (correlated scalar subquery)
SELECT c.first_name, c.last_name,
(SELECT COUNT(*) FROM orders o WHERE o.customer_id = c.customer_id) AS order_count,
(SELECT MAX(total_amount) FROM orders o WHERE o.customer_id = c.customer_id) AS max_order
FROM customers c;
-- Her müşteri için 2 subquery çalışır — 10 müşteri = 20 subquery çağrısı!
-- JOIN alternatifi (daha verimli):
SELECT c.first_name, c.last_name,
COUNT(o.order_id) AS order_count,
MAX(o.total_amount) AS max_order
FROM customers c
LEFT JOIN orders o ON c.customer_id = o.customer_id
GROUP BY c.customer_id, c.first_name, c.last_name;Sıkça Yapılan Hatalar
Correlated subquery'nin N kere çalıştığını bilmemek: 10.000 satırlık tabloda 10.000 kere subquery = çok yavaş.
JOIN ile yazılabilecek correlated subquery: Çoğu correlated subquery JOIN'e dönüştürülebilir ve genellikle daha hızlıdır.
SELECT'te çoklu correlated subquery: Her biri ayrı ayrı çalışır. JOIN + GROUP BY ile tek sorguda çöz.
Özet
Non-correlated subquery: dış sorgudan bağımsız, 1 kere çalışır, genellikle hızlı
Correlated subquery: dış sorguya bağımlı, her satır için çalışır, N kez çalışır
Correlated subquery'ler güçlü ama performans maliyetli — mümkünse JOIN'e çevir
EXISTS doğası gereği correlated'dır ve genellikle iyi optimize edilir
AI Asistan
Sorularını yanıtlamaya hazır