← Kursa Dön
📄 Text · 35 min

Subquery Nedir? WHERE'da Subquery

Giriş — Sorgu İçinde Sorgu

Bazen bir soruyu cevaplamak için önce başka bir soruyu cevaplaman gerekir: "Ortalama fiyattan pahalı ürünleri göster" — önce ortalamayı hesapla, sonra o değerden büyük olanları filtrele. İşte subquery (alt sorgu) bir sorgunun içinde çalışan başka bir sorgudur.

🎯 Analoji: Bir soruyu cevaplamak için ansiklopedi açıyorsun, orada başka bir kavrama atıfta bulunuyor, onu da araştırıyorsun. Subquery, SQL'in "iç içe arama" mekanizmasıdır.


Temel Subquery — WHERE'da Kullanım

-- Ortalama fiyattan pahalı ürünler
SELECT product_name, price
FROM products
WHERE price > (SELECT AVG(price) FROM products);
-- Subquery önce çalışır: AVG(price) = 13009.99
-- Sonra dış sorgu: price > 13009.99 olan ürünler

-- En son sipariş veren müşteriyi bul
SELECT first_name, last_name
FROM customers
WHERE customer_id = (
    SELECT customer_id FROM orders ORDER BY order_date DESC LIMIT 1
);

-- En pahalı ürünü bul
SELECT product_name, price
FROM products
WHERE price = (SELECT MAX(price) FROM products);

IN ile Subquery — Birden Fazla Değer

-- Sipariş vermiş müşteriler
SELECT first_name, last_name
FROM customers
WHERE customer_id IN (SELECT DISTINCT customer_id FROM orders);

-- Elektronik kategorisindeki (ve alt kategoriler) ürünler
SELECT product_name, price
FROM products
WHERE category_id IN (
    SELECT category_id FROM categories 
    WHERE category_name IN ('Elektronik', 'Bilgisayar', 'Telefon')
);

-- Ocak ayında sipariş edilen ürünler
SELECT product_name
FROM products
WHERE product_id IN (
    SELECT DISTINCT oi.product_id
    FROM order_items oi
    INNER JOIN orders o ON oi.order_id = o.order_id
    WHERE MONTH(o.order_date) = 1 AND YEAR(o.order_date) = 2024
);

NOT IN ile Subquery

-- Hiç sipariş vermemiş müşteriler
SELECT first_name, last_name
FROM customers
WHERE customer_id NOT IN (
    SELECT DISTINCT customer_id FROM orders
);

⚠️ Dikkat: NOT IN subquery'den NULL dönerse hiçbir satır dönmez! Çünkü x NOT IN (1, 2, NULL) her zaman UNKNOWN döndürür. ``sql -- Güvenli yol: WHERE koşuluyla NULL'ları ele WHERE customer_id NOT IN ( SELECT customer_id FROM orders WHERE customer_id IS NOT NULL ); -- Veya NOT EXISTS kullan (NULL-safe) ``


Karşılaştırma Operatörleriyle Subquery

-- Ortalamadan pahalı
WHERE price > (SELECT AVG(price) FROM products)

-- Minimum fiyattan ucuz olmayan
WHERE price >= (SELECT MIN(price) FROM products WHERE category_id = 2)

-- Belirli bir müşterinin sipariş sayısından fazla sipariş verenler
SELECT customer_id, COUNT(*) AS cnt
FROM orders
GROUP BY customer_id
HAVING COUNT(*) > (
    SELECT COUNT(*) FROM orders WHERE customer_id = 1
);

Gerçek Dünya Örneği

-- Bu ay ortalamasının üstünde sipariş veren müşteriler
SELECT c.first_name, c.last_name, SUM(o.total_amount) AS total
FROM customers c
INNER JOIN orders o ON c.customer_id = o.customer_id
WHERE MONTH(o.order_date) = MONTH(NOW()) AND YEAR(o.order_date) = YEAR(NOW())
GROUP BY c.customer_id, c.first_name, c.last_name
HAVING SUM(o.total_amount) > (
    SELECT AVG(monthly_total) FROM (
        SELECT SUM(total_amount) AS monthly_total
        FROM orders
        WHERE MONTH(order_date) = MONTH(NOW()) AND YEAR(order_date) = YEAR(NOW())
        GROUP BY customer_id
    ) AS monthly_avgs
);

Sıkça Yapılan Hatalar

  1. Scalar subquery birden fazla satır döndürür: WHERE price = (SELECT price FROM products) hata verir — tek satır bekleniyor. IN kullan veya LIMIT ekle.

  2. NOT IN ve NULL: NULL değer subquery sonucundaysa NOT IN çalışmaz. NOT EXISTS tercih et.

  3. Performans: Correlated subquery her satır için çalışır — büyük tablolarda yavaş. JOIN'e çevirmeyi düşün.


Özet

  • Subquery bir sorgunun içinde çalışan başka bir sorgudur

  • WHERE'da =, >, <, IN, NOT IN ile kullanılır

  • Scalar subquery tek değer, IN subquery çoklu değer döndürür

  • NOT IN ile NULL dikkat — NOT EXISTS daha güvenli

  • Subquery parantez içine yazılır ve ilk çalışan odur