SQL JOIN MANTIĞI

SQL JOIN türlerini iki tablonun kesişen Venn dairesi ve maroon veritabanı silindiri ile özetleyen sade kompozisyon

Müşteri listesinde 1.200 kayıt var, sipariş tablosunda 4.800. Yöneticiniz "her müşterinin toplam siparişini görmek istiyorum" diyor. Yanlış join seçerseniz raporda ya hiç sipariş vermemiş müşteriler kaybolur ya da boşta kalan siparişler iki kez sayılır. JOIN, SQL'in en güçlü ama en çok yanlış kullanılan yapısıdır.

Örnek veritabanını indir (.sql) — 1.200 müşteri ve 4.800 siparişle JOIN alıştırması (SatisDB)

JOIN Nedir, Neden Gerekir?

İlişkisel veritabanlarında veri tek bir büyük tabloda tutulmaz. Müşteriler ayrı, siparişler ayrı, ürünler ayrı tabloda durur. Aralarındaki bağlantı anahtarlar (genellikle customer_id, order_id gibi) üzerinden kurulur. JOIN, bu ayrık tabloları belirli bir anahtar üzerinden geçici olarak birleştirip tek bir sonuç kümesi üretir.

Asıl mesele veriyi birleştirmek değil, hangi kayıtların sonuca girip hangilerinin dışarıda kalacağına karar vermektir. İşte burada JOIN türleri devreye girer.

INNER JOIN — Kesişim Kümesi

INNER JOIN, sadece iki tarafta da eşleşmesi olan kayıtları getirir. Venn diyagramındaki iki dairenin ortasına denk gelir.

SELECT m.MusteriAdi, s.ToplamTutar
FROM Musteriler m
INNER JOIN Siparisler s ON m.MusteriID = s.MusteriID;

Sipariş vermemiş müşteriler bu sonuçta görünmez. Sipariş tablosunda olup müşteri tablosunda silinmiş bir musteri_id varsa o sipariş de gelmez. "Sadece eşleşenleri istiyorum" senaryosunda doğru tercih budur — örneğin "bu ay sipariş veren müşterilerin listesi".

LEFT JOIN — Soldakini Koru

LEFT JOIN soldaki tablonun tüm kayıtlarını getirir, sağ tarafta eşleşme yoksa NULL doldurur. Pratikte en çok kullanılan join türüdür çünkü çoğu rapor "ana liste eksiksiz olsun" mantığıyla kurulur.

SELECT m.MusteriAdi,
       COALESCE(SUM(s.ToplamTutar), 0) AS ToplamHarcama
FROM Musteriler m
LEFT JOIN Siparisler s ON s.MusteriID = m.MusteriID
GROUP BY m.MusteriID, m.MusteriAdi
ORDER BY ToplamHarcama ASC;
Management Studio ekranında LEFT JOIN sorgusu ve sipariş vermemiş müşterilerin sıfır harcamayla listelendiği sonuç tablosu

Sonuç grid'inin başında toplamı 0,00 olan satırlar görünüyor — bunlar hiç sipariş vermemiş müşteriler. Girişteki 1.200 kişilik tabloda tam 60 müşteri bu durumda; INNER JOIN kullansaydık bu 60 kişi rapordan sessizce kaybolacaktı. COALESCE kullanmazsanız NULL değerler raporda boş hücre olarak görünür — Excel'e açtığınızda formüller patlar.

RIGHT JOIN — Sağdakini Koru

LEFT JOIN'in aynası. Sağdaki tablonun tüm kayıtları gelir, soldakinde eşleşme yoksa NULL olur. Daha ileri ayrıntılar Wikipedia'nın SQL sayfasında ele alınır. Uygulamada nadiren tercih edilir; çoğu geliştirici tabloların sırasını değiştirip LEFT JOIN yazmayı daha okunaklı bulur.

RIGHT JOIN'i, tabloların sırasını değiştirmek karmaşa yaratacaksa (örneğin uzun bir FROM zincirinin sonunda) okunabilirliği bozmamak adına bırakabilirsiniz.

FULL OUTER JOIN — İki Tarafı Da Koru

FULL JOIN her iki tablodaki tüm kayıtları getirir. Eşleşme yoksa karşı tarafta NULL doldurur. Veri kalitesi kontrolünde altın değerindedir.

SELECT m.MusteriID, s.MusteriID
FROM Musteriler m
FULL OUTER JOIN Siparisler s ON m.MusteriID = s.MusteriID
WHERE m.MusteriID IS NULL OR s.MusteriID IS NULL;

Bu sorgu iki tabloda da eşleşmesi olmayan yetim kayıtları tek seferde listeler. Veri ambarına yeni veri yüklendikten sonra bütünlük kontrolü için sık başvurulan bir kalıptır.

Hangi JOIN Ne Zaman?

  • INNER JOIN: Sadece iki tarafta da olan kayıtları istiyorsunuz. Aktif müşteri-sipariş eşleşmesi gibi.
  • LEFT JOIN: Ana listeniz tam olmalı, ek bilgi varsa görünsün, yoksa boş kalsın. "Tüm ürünlerin satış raporu" gibi.
  • RIGHT JOIN: Nadiren; tablo sırası değişmeyecekse.
  • FULL OUTER JOIN: Eşleşmeyenler dahil her şeyi görmek istiyorsanız. Veri kalitesi kontrolü, mutabakat raporları.
  • CROSS JOIN: Kartezyen çarpım. Tüm kombinasyonları üretir; takvim x ürün gibi senaryolarda.
INNER LEFT RIGHT FULL ve CROSS JOIN türlerini 5 küçük Venn diyagramı paneli ile karşılaştıran özet diyagram

Sık Yapılan Hatalar

JOIN yazarken karşılaşılan tipik hatalar genellikle aynı kalıplardan çıkar. Çoğunu önceden bilmek saatlerce hata ayıklamadan tasarruf sağlar.

WHERE ile LEFT JOIN'i Bozma

LEFT JOIN sonrası sağ tablodaki bir kolona WHERE koşulu yazarsanız, NULL kayıtlar elenir ve sorgunuz örtük şekilde INNER JOIN'e dönüşür:

-- YANLIŞ: sipariş vermeyenler kaybolur
SELECT m.MusteriAdi FROM Musteriler m
LEFT JOIN Siparisler s ON m.MusteriID = s.MusteriID
WHERE s.ToplamTutar > 0;

-- DOĞRU: koşul ON içine
SELECT m.MusteriAdi FROM Musteriler m
LEFT JOIN Siparisler s ON m.MusteriID = s.MusteriID
                      AND s.ToplamTutar > 0;

Çoklu Eşleşme — Beklenmedik Çoğalma

Bir müşterinin 5 siparişi varsa, müşteri tablosunu sipariş tablosuyla join ettiğinizde o müşteri sonuçta 5 kez görünür. Toplam alırken sorun yok, ama listeye DISTINCT eklemediğinizde rapor tekrarlı satırlarla şişer.

Performans Notu

Büyük tablolarda join performansı, join anahtarlarındaki indekslerle doğrudan ilişkilidir. musteri_id kolonunda indeks yoksa veritabanı tüm tabloyu taramak zorunda kalır. Sorgu planını EXPLAIN (PostgreSQL/MySQL) veya tahmini yürütme planı (SQL Server) ile inceleyerek nerede tablo taraması yapıldığını görebilirsiniz. JOIN'leri ve indeksleri etkin kullanmayı sistematik öğrenmek için yapılandırılmış SQL eğitimi içeriğini inceleyebilirsiniz.

Doğru join seçimi sadece teknik bir tercih değil, raporun doğruluğunu belirleyen bir karar. Bir kez yanlış kurulan join, aylarca yanlış sayılarla karar verilmesine yol açabilir.

Sıkça Sorulan Sorular

INNER JOIN ile JOIN aynı şey mi?

Çoğu veritabanı motorunda evet. Sadece JOIN yazdığınızda varsayılan olarak <strong>INNER JOIN</strong> davranışı uygulanır. Okunabilirlik açısından ekiple birlikte çalışıyorsanız INNER JOIN şeklinde açık yazılması önerilir; niyetiniz net görünür.

LEFT JOIN sonrası WHERE neden kayıt kaybettirir?

LEFT JOIN sağ tarafta eşleşme yoksa NULL koyar. Sağ taraftaki bir kolona WHERE ile koşul yazarsanız NULL'lar koşulu sağlayamaz ve elenir; sorgu örtük <strong>INNER JOIN</strong>'e döner. Filtreyi ON içine almak bu sorunu çözer.

FULL OUTER JOIN her veritabanında çalışır mı?

PostgreSQL, SQL Server ve Oracle FULL OUTER JOIN'i destekler. MySQL doğrudan desteklemez; UNION ile LEFT JOIN ve <strong>RIGHT JOIN</strong> birleştirilerek aynı sonuç elde edilir. MariaDB de aynı kısıtlamaya sahiptir.

CROSS JOIN ne zaman kullanılır?

Tüm kombinasyonları üretmek istediğinizde. Örneğin her gün için her ürünün satış raporunda boş günleri görmek istiyorsanız tarih tablosu ile ürün tablosunu CROSS JOIN ile çoğaltır, sonra siparişlerle <strong>LEFT JOIN</strong> edersiniz. Filtre koymadan büyük tablolarda kullanmak tehlikelidir.

Üç veya daha fazla tabloyu join etmek performansı bozar mı?

Sayı tek başına sorun değil, anahtarların indeksli olması ve join sırası belirleyici. Veritabanı optimizer'ı çoğu zaman doğru sırayı seçer; ancak büyük tablolarda EXPLAIN planı inceleyerek darboğazı görmek gerekir.

Self JOIN nedir, nerede işe yarar?

Bir tablonun kendisiyle join edilmesi. Hiyerarşik veri için sık kullanılır: çalışan tablosunda her kaydın yöneticisi de aynı tabloda olduğunda, çalışan ile yöneticisini eşleştirmek için tabloya iki farklı takma adla erişip self join yapılır.

USING ve ON arasındaki fark nedir?

ON, herhangi iki kolon arasında ilişki kurmaya izin verir ve farklı isimli kolonlarda da çalışır. USING ise iki tabloda aynı isimli kolonlar için kısa yazımdır ve birleşmiş kolon sonuçta tek seferde görünür. ON daha esnek ve okunaklıdır.