← Kursa Dön
📄 Text · 30 min

Scalar, Row ve Table Subquery

Giriş — Subquery'nin Üç Farklı Boyutu

Subquery'ler döndürdükleri verinin şekline göre üç türe ayrılır. Her tür farklı yerlerde kullanılır.


1. Scalar Subquery — Tek Değer

Tek satır, tek sütun döndürür. Tek bir değer (sayı, string, tarih):

-- SELECT'te scalar subquery (hesaplanmış sütun)
SELECT product_name, price,
       price - (SELECT AVG(price) FROM products) AS diff_from_avg,
       ROUND(price / (SELECT MAX(price) FROM products) * 100, 1) AS pct_of_max
FROM products
ORDER BY price DESC;

-- WHERE'da scalar subquery
SELECT * FROM products
WHERE price = (SELECT MAX(price) FROM products);

-- UPDATE'te scalar subquery
UPDATE orders 
SET total_amount = (
    SELECT SUM(quantity * unit_price * (1 - discount_percent/100))
    FROM order_items WHERE order_items.order_id = orders.order_id
)
WHERE order_id = 1;

⚠️ Scalar subquery birden fazla satır döndürürse HATA alırsın. LIMIT 1 ekle veya aggregate fonksiyon kullan.


2. Row Subquery — Tek Satır, Çoklu Sütun

Tek satır ama birden fazla sütun döndürür:

-- En pahalı ürünün adını ve fiyatını tek sorguyla bul
SELECT * FROM products
WHERE (category_id, price) = (
    SELECT category_id, MAX(price) 
    FROM products 
    WHERE category_id = 2
    GROUP BY category_id
);

-- Birden fazla sütun karşılaştırması
SELECT * FROM order_items
WHERE (order_id, product_id) = (
    SELECT order_id, product_id FROM order_items ORDER BY unit_price DESC LIMIT 1
);

3. Table Subquery — Çoklu Satır, Çoklu Sütun

Bir tablo gibi davranır. Genellikle FROM'da veya IN ile kullanılır:

-- FROM'da (derived table / türetilmiş tablo)
SELECT city, avg_order
FROM (
    SELECT c.city, ROUND(AVG(o.total_amount), 2) AS avg_order
    FROM customers c
    INNER JOIN orders o ON c.customer_id = o.customer_id
    GROUP BY c.city
) AS city_orders
WHERE avg_order > 10000;

-- IN ile
SELECT * FROM customers
WHERE customer_id IN (
    SELECT customer_id FROM orders GROUP BY customer_id HAVING COUNT(*) > 2
);

💡 FROM'daki subquery'ye alias vermek zorunludur (AS city_orders).


Karşılaştırma Tablosu

TürDöndürdüğüKullanıldığı YerÖrnek
Scalar1 değerSELECT, WHERE, HAVING(SELECT AVG(price) FROM products)
Row1 satır, N sütunWHERE (çoklu sütun karşılaştırma)WHERE (a, b) = (SELECT ...)
TableN satır, M sütunFROM, IN, EXISTSFROM (SELECT ...) AS t

Özet

  • Scalar: tek değer → SELECT, WHERE, SET'te kullanılır

  • Row: tek satır, çoklu sütun → çoklu sütun karşılaştırmasında

  • Table: çoklu satır → FROM'da derived table, IN listesi olarak

  • FROM'daki subquery'ye alias zorunlu

  • Scalar subquery birden fazla satır döndürürse hata alırsın