Soldaki her satır kalsın
LEFT JOIN (LEFT OUTER JOIN), sol tablodaki tüm satırları döndürür. Sağda eşi yoksa sağ tablonun sütunları NULL gelir.
SELECT d.name AS departman, e.first_name FROM departments d LEFT JOIN employees e ON e.dept_id = d.dept_id ORDER BY d.dept_id;
Hukuk departmanında çalışan olmadığı için o satırda first_name NULL görünür. INNER JOIN kullansaydık Hukuk hiç görünmezdi.
Anti-join: hiç sipariş vermemiş müşteriler
LEFT JOIN'den sonra sağ tablonun anahtarı NULL olan satırları seçmek, “eşi olmayanları” bulmanın klasik yoludur:
SELECT c.customer_id, c.first_name, c.last_name FROM customers c LEFT JOIN orders o ON o.customer_id = c.customer_id WHERE o.order_id IS NULL;
ON mu WHERE mi?
LEFT JOIN'de sağ tabloya ait filtreyi WHERE'e yazarsan, NULL satırlar elenir ve sorgu farkında olmadan INNER JOIN'e dönüşür. Filtreyi ON içine yazarsan sol tablo korunur:
-- Her müşteri ve 2024'teki sipariş sayısı (siparişi olmayan 0 görünür)
SELECT c.customer_id, COUNT(o.order_id) AS siparis_2024
FROM customers c
LEFT JOIN orders o
ON o.customer_id = c.customer_id
AND o.order_date >= '2024-01-01'
GROUP BY c.customer_id
ORDER BY siparis_2024
LIMIT 10;
COUNT(o.order_id)) doğru sonucu verir.Derinleş: ON ile WHERE farkı tek tabloda
| Yazım | Sonuç |
|---|---|
LEFT JOIN o ON o.courier_id = c.courier_id AND o.status = 'teslim' | Tüm kuryeler; teslimatı olmayanlar NULL ile |
LEFT JOIN o ON o.courier_id = c.courier_id WHERE o.status = 'teslim' | Yalnızca teslimatı olan kuryeler (fiilen INNER JOIN) |
... WHERE o.order_id IS NULL | Yalnızca eşi olmayanlar (anti-join) |
LEFT JOIN sonrası COUNT(*) eşi olmayan satırı 1 sayar; COUNT(sağ_tablo.anahtar) 0 sayar.