SQL JOIN: İki Tabloyu Doğru Şekilde Birleştirmek
Sipariş ve müşteri gibi iki tabloyu SQL'de birleştirmenin pratik yolu: INNER JOIN ile LEFT JOIN farkı, satırların çoğalması tuzağı ve dört veritabanında çalışan gerçek örnekler.
Verinin çoğu iki ayrı yerde durur. Siparişler bir tabloda, o siparişi veren müşterinin adı ve şehri başka bir tabloda. "Geçen ay İstanbul'daki müşteriler ne kadar sipariş verdi?" diye sorduğunuzda cevap ikisinin kesişiminde saklıdır. SQL'de iki tabloyu bir araya getiren komutun adı JOIN'dir; aslında ilk bakışta göründüğünden çok daha basittir.
Tablolar neden ayrı durur?
Aynı müşterinin adını her siparişte baştan yazmak yerine, müşteriyi bir kez musteriler tablosuna kaydeder, siparişte yalnızca musteri_id tutarsınız. Buna normalizasyon denir; yerden kazandırır ve bir müşterinin adını tek noktadan güncellemenizi sağlar. Bedeli şu: rapor çıkarırken bu tabloları yeniden birleştirmeniz gerekir.
INNER JOIN nasıl yazılır?
En sık kullanılan tür budur ve iki tablodaki eşleşen satırları getirir. musteriler ile siparisler tablolarını musteri_id üzerinden bağlayalım:
SELECT m.ad, s.tutar, s.tarih
FROM siparisler s
INNER JOIN musteriler m ON m.id = s.musteri_id;ON satırı eşleşmenin kuralıdır: hangi kolon hangisine denk geliyor. s ve m takma adları (alias) sorguyu kısaltır. INNER JOIN yalnızca iki tarafta da karşılığı olan satırları döndürür; müşterisi silinmiş bir sipariş varsa listeye hiç girmez.
Hiç siparişi olmayan müşterileri de görmek istersem?
Klasik soru budur ve INNER JOIN bunu gösteremez, çünkü eşleşme yoktur. LEFT JOIN sol taraftaki (burada musteriler) her satırı korur; sağda karşılığı yoksa o kolonları NULL bırakır:
SELECT m.ad
FROM musteriler m
LEFT JOIN siparisler s ON s.musteri_id = m.id
WHERE s.id IS NULL;WHERE s.id IS NULL filtresi, sağ tarafta hiç eşleşme bulunmayan (yani hiç siparişi olmayan) müşterileri süzer. Bu, LEFT JOIN'in en çok işe yarayan kalıplarından biridir.
En sinsi hata: satırların çoğalması
Bir müşterinin beş siparişi varsa, JOIN sonucunda o müşteri beş satır olarak görünür. Bunu fark etmeden satır sayar ya da müşteriyi "tek" sanıp ortalama alırsanız sonuç şişer. Pratikteki kural: birleştirdikten sonra genellikle gruplayıp toplarsınız.
SELECT m.ad,
COUNT(s.id) AS siparis_sayisi,
SUM(s.tutar) toplam
FROM musteriler m
INNER JOIN siparisler s ON s.musteri_id = m.id
GROUP BY m.ad
ORDER BY toplam DESC;Buradaki GROUP BY ve toplama işini ayrı bir yazıda tek tek ele aldık; JOIN sonrası neredeyse her zaman bu adım gelir.
Veritabanına göre değişen bir şey var mı?
İyi haber: INNER JOIN ve LEFT JOIN sözdizimi PostgreSQL, SQL Server, MySQL ve Oracle'da aynıdır. Tek dikkat noktası, eski Oracle kodlarında (+) işaretiyle yazılmış dış birleştirmelerdir; yeni sorgu yazarken standart LEFT JOIN'i tercih edin. FULL OUTER JOIN ise MySQL'de hiç yoktur; aynı sonucu iki LEFT JOIN'i UNION ile birleştirerek elde edersiniz.
Sık sorulan sorular
- INNER JOIN ile LEFT JOIN arasındaki fark nedir?
- INNER JOIN yalnızca iki tabloda da eşleşen satırları getirir. LEFT JOIN sol tablodaki tüm satırları korur; sağda karşılığı yoksa o kolonlar NULL gelir. "Karşılığı olmayanları da göreyim" dediğiniz her durumda LEFT JOIN gerekir.
- İkiden fazla tabloyu birleştirebilir miyim?
- Evet. Her tablo için bir JOIN ... ON satırı eklersiniz; örneğin sipariş kalemlerini siparişlere, siparişleri de müşterilere zincirleyebilirsiniz. Tablo sayısı arttıkça sorgunun yavaşlamaması için birleştirdiğiniz kolonlarda indeks olması önemlidir.
- ON ile WHERE arasındaki fark nedir?
- ON, iki tablonun nasıl eşleşeceğini söyler; WHERE ise birleşmiş sonucu filtreler. INNER JOIN'de ikisi çoğu zaman benzer davranır, ama LEFT JOIN'de koşulu ON'a mı yoksa WHERE'e mi koyduğunuz sonucu tamamen değiştirir.
- JOIN yerine alt sorgu mu kullanmalıyım?
- Duruma göre. Başka tablodan kolon göstereceksen JOIN daha uygundur; yalnızca "şu listede var mı?" diye süzeceksen alt sorgu daha okunur olabilir. İkisini karşılaştıran ayrı bir rehberimiz var.
Bu JOIN'i her rapor için elden yazmak yerine PerSight'a Türkçe sorabilirsiniz: "her müşterinin toplam sipariş tutarını büyükten küçüğe sırala" dediğinizde sorguyu kurar, ürettiği SQL'i önünüze koyar ve gerekirse düzeltmeyi size bırakır.
Kaynaklar
İlgili yazılar
- SQL GROUP BY: Gruplayıp Toplamayı AnlamakAylık ciro, müşteri başına sipariş, kategoriye göre adet: GROUP BY ile toplama. COUNT/SUM/AVG, WHERE ile HAVING farkı ve MySQL'in ONLY_FULL_GROUP_BY tuzağı, gerçek örneklerle.
- SQL Alt Sorgu (Subquery): Ne Zaman, Nasıl ve NOT IN TuzağıSorgu içinde sorgu: skaler alt sorgu, IN, EXISTS ve ilişkili (correlated) alt sorgular. NOT IN'in NULL ile neden boş sonuç döndürdüğü ve JOIN'e göre ne zaman tercih edileceği.
- Doğal Dille Veritabanı Sorgulama Nasıl Çalışır (ve Görünür Sorgu Neden Önemli)Doğal dilden SQL üretimi sade bir anlatımla: sorunuz nasıl sorguya dönüşür, salt-okunur ve her zaman görünür bir sorgu neden daha güvenli ve PerSight verinizi neden makinenizde tutar.