MySQL Join (LEFT, RIGHT, INNER, CROSS) Kullanımı ve Örnekleri
MySQL üzerinde LEFT JOIN, RIGHT JOIN, INNER JOIN ve CROSS JOIN kullanımı
Join Nedir (Wiki: en) ?
Kısaca join; birbiriyle alakalı olan iki veya daha fazla tablolardan tek seferde veri çekme/filtreleme/sıralama işlemine yaramaktadır.
Join Kullanırken Yapılan En Büyük Hata Sütun Veri Tip ve Uzunluklarının Farklı Olmasıdır :
Evet, join yapılacak tabloların tablolar arası bağlantıyı kuran sütunların veri tipleri ve veri uzunlukları birbirinden farklıysa join kullanmak sorguyu çok uzatır ve performans kaybı yaşarsınız (yazımızın üçüncü sayfasından itibareb detaylar mevcut).
Örnek Senaryo :
Dört adet tablomuz olsun bunlardan ilki ürün listesi tutan urun tablosu, ikinci tablomuz ise ürünlerin detaylarını tutan urun_detay tablosu, üçüncü tablo firmamıza kayıtlı olan müşterileri tutacak olan musteri tablosu, son tablomuzda müşterilerimize satış yaptığımız ürünlerin kaydını tutan tablo satis olsun.
INNER JOIN Kullanımı:
İlk olarak en yaygın kullanılan JOIN tipi olan INNER JOIN ‘i inceleyeceğiz. INNER JOIN seçtiğiniz tablolarda birebir eşleşen kayıtları getirir. Örneğin musteri ve musteri_detay tablolarını inceleyecek olursanız 6 adet müşteri kaydımız ve 2 adet müşteri detay kaydımız bulunuyor. Biz bu tablolar için INNER JOIN kullanırsak bize sadece 2 satır kayıt dönecektir. Çünkü her iki tabloda kaydı bulunan musteri sadece 2 tanedir.
FROM firmam.musteri AS m
INNER JOIN firmam.musteri_detay AS md ON m.musteri_id = md.musteri_id
Yukarıdaki sorgumuzda sonuç sütunlarının ekrana sığması açısından musteri tablosundaki tüm sütunları, musteri_detay tablosundaki musteri_detay_website sütununu seçtik. Siz isterseniz “*” kullanarak hepsini seçebilirsiniz. Zaten büyük tablololarda performans kazanmak için gerekmeyen sütunların seçilmemesi önerilir.
INNER JOIN kullanarak bir örnek daha yapmış olalım. Bizden İstanbul ‘da olan müşterilerin adı, soyadı ve telefon bilgileri isteniyor olsun. Sorgumuz aşağıdaki gibi olacaktır.
FROM firmam.musteri AS m
INNER JOIN firmam.musteri_detay AS md ON m.musteri_id = md.musteri_id
WHERE md.musteri_detay_sehir = 'İstanbul'
Bir başka INNER JOIN örneği
Şimdide hem 3 tabloyu JOIN yapmayı inceleyelim hemde sorgumuzu biraz daha karşamık hale getirelim. Bizden kısaca kime, hangi ürünü, kaç adet, toplam ne kadara? sorularının SQL sonuçlarını istiyor olsunlar.
Burada yapacağımız şey satış tablosundan yola çıkarak müşteri bilgilerini almak için müşteri tablosunu satış tablosuna JOIN yapmak ve daha sonra ürün bilgilerini almak için ürün tablosunu satış tablosuna JOIN yapmak olacak.
FROM firmam.satis AS s
INNER JOIN firmam.musteri AS m ON s.musteri_id = m.musteri_id
INNER JOIN firmam.urun AS u ON s.urun_id = u.urun_id
WHERE 1
ORDER BY m.musteri_id
JOIN İle USING Kullanımı
Tüm JOIN tiplerinde ON clause yerine USING kullanılabilir. USING kullanmanın kısıtlamaları ise her iki tabloda da aynı ada sahip sütunların olması gerekliliğidir. İlk sorgumuzu USING kullanarak yeniden yazalım.
FROM firmam.musteri AS m
INNER JOIN firmam.musteri_detay AS md USING(musteri_id)
JOIN Kullanırken “#1052 – Column ‘column_name’ in where clause is ambiguous” Hatası Almak
Örneğin sizden musteri_id si 1 olan musterinin tüm bilgilerini isterlerse aşağıdaki sorguyu yazarak sonuca ulaşmak isteyebilirsiniz. Ancak MySQL size “#1052 – Column ‘musteri_id’ in where clause is ambiguous” hatası döner. Bunun sebebi seçilen sütunların arasında aynı adı taşıyanlar olması ve sizin buna filtre uygulamaya çalışmanızdır. Örneğin aşağıdaki örnekte musteri_id si 1 olan kaydı getir dedik ancak musteri_id her iki tabloda da bulunduğundan MySQL ‘in biraz kafası karışır. Bu örnek tam yerinde olmamakla birlikte zaten bu sorguyu doğru çalıştırması asıl bizim başımızı ağrıtabilir. Bu sebeple birden fazla tablo kullanıyorsak SELECT, WHERE, GROUP BY, ORDER vb. bölümlerinde mutlaka tablo adı yada tablo aliaslarını (lakaplarını) bebelirtmek yarayımıza olacaktır.
Yanlış Kullanım:
FROM firmam.musteri AS m
INNER JOIN firmam.musteri_detay AS md ON m.musteri_id = md.musteri_id
WHERE musteri_id = 1
Doğru Kullanım:
FROM firmam.musteri AS m
INNER JOIN firmam.musteri_detay AS md ON m.musteri_id = md.musteri_id
WHERE m.musteri_id = 1
LEFT JOIN Kullanımı
LEFT JOIN, seçilen tablolardan soldaki bulunan tablonun tamamını alır ve sağdaki tablodan da varsa eşleşen kayıtları alır yoksa NULL ile doldurulmuş kayıtlar döner.
Bir örnekle pekiştirmeye çalışalım. Veritabanında kayıtlı müsterileri ve varsa müşteri detay bilgilerini almamız gerektiğini varsayalım. INNER JOIN ‘i hatırlayacak olursak her iki tabloda da musterinin bulunması zorunluluğu vardı ama LEFT JOIN kullandığınızda bu zorunluluk ortadan kalkıyor.
Müşteri ve Varsa Müşteri Detay Bilgilerini Alan SQL :
FROM firmam.musteri AS m
LEFT JOIN firmam.musteri_detay AS md ON m.musteri_id = md.musteri_id
WHERE 1
Sorgu sonucunu bir önceki sayfada bulunan INNER JOIN örneğinde ki sonuç ile karşılaştırdığımızda 4 adet fazla kayıt döndüğünü görürüz. LEFT JOIN kullandığımızda soldaki tabloda (musteri tablosu) bulunan kayıtların tamamını alır (6 adet), sağdaki tablonun ise (musteri_detay) eşleşen kayıtlar (musteri_id ile) varsa birleştirir yoksa NULL basarak satırı doldurur.
Soldaki tablo kendisinden önce yazılan tablo anlamına gelir. Yani musteri AS m LEFT JOIN musteri_detay AS md sorgusunda musteri tablosu musteri_detay tablosundan önce yazıldığından soldaki tablo olarak anılır. Sorguyu musteri _detayAS md LEFT JOIN musteri AS m şeklinde yazarsak soldaki tablo bildiğiniz gibi musteri_detay olacaktır.
1:n Relationships (birden çoğa bağlantı) Durumunda LEFT JOIN Davranışı :
Birden çoğa bağlantılı tabloları LEFT JOIN ile birleştirdiğimizde n tarafındaki tablodaki varlık kadar satır tekrarı yapılacaktır. Bunun anlamı müşteriler tablomuz ile satış tablomuzu LEFT JOIN ile birleştirirsek müşteriye yapılan satış sayısı kadar müşteri kaydı satır tekrarlaması yapılacaktır. Biraz daha açacak olursak müşteri tablomuzda aynı musteri_id ‘si ile sadece bir adet kayıt bulunabilir. Ancak bir müşteriye birden fazla satış yapabileceğimiz için satış tablosunda birden fazla musteri_id ye sahip kayıt bulunabilir.
Bir örnekle inceleyelim:
FROM firmam.musteri AS m
LEFT JOIN firmam.satis AS s ON m.musteri_id = s.musteri_id
WHERE 1
Yukarıdaki sorgu sonucunu inceleyecek olursak müşteri bilgilerinin tekrarladığını göreceğiz. Bizim 6 adet müşterimiz olmasına rağmen 15 adet sorgu sonucu dönmüş durumda. Önemli bir hatırlatma: buradaki sorgu sonucu sayısı sadece satış tablosunun kayıt sayısına eşit değildir. Bu tip birleştirmelerde sorgu sayısı sonucu 1 tarafındaki (musteri) tablo ile n tarafındaki (satış) tablosu arasındaki ortak kayıtlar + 1 tarafındaki (müşteri) tablodaki ortak olmayan kayıtlar şeklindedir. Hesaplayacak olursak, satış tablosundaki kayıtların hepsini müşteri tablosuna ortak (musteri_id sinin karşılığı musteri tablosunda var) olduğunu için tamamı (15 adet) + musteri tablosunda olup satis tablosunda olmayan kayıtlar (0 adet) yani toplamda 15+0 = 15 satır.
Gelişmiş LEFT JOIN Kullanımı :
Şimdi biraz basit LEFT JOIN birleştirmelerini bir adım daha ileriye taşımak için küçük bir örnek daha yapalım. Klasik LEFT JOIN birleştirmesi aslında nette onlarca ve hatta yüzlerce bulabileceğiniz bir örnektir. Ancak detaylı bir sorgu istediğimizde (ilk zamanlarda bizimde yaşadığımız) örnek bulma konusunda zaman zaman güçlük çekilebiliyor.
Örneğimizde kayıtlı ürünlerin tam listesi ile birlikte varsa 01-12-2010 (2010-12-01 Y-m-d) tarihinde yapılan satışların bilgileri isteniyor olsun.
FROM firmam.urun AS u
LEFT JOIN firmam.satis AS s ON u.urun_id = s.urun_id
AND s.satis_tarih BETWEEN '2010-12-01 00:00:00' AND '2010-12-01 23:59:59'
WHERE 1
Sorgu sonucunda görüldüğü gibi 3 adet kayıt döndü. Sorguyu inceleyecek olursak ON clause kısmından sonra AND diyerek JOIN işlemine devam ettik. MySQL burada sağdaki tablodan sadece belirttiğimiz tarih aralığına uyan kayıtları seçti ve soldaki tabloya normal LEFT JOIN işlemiyle birleştirme yaptı. Eğer tarih aralığını WHERE kısmında verirseniz dönen satır sayısı 2 olacaktır. Bu sorgu senaryosu tam olarak gerçeği yansıtmıyor gibi görülebilir ancak bazen çok gerekli bir yöntem oluyor.
Sorgudan anlaşılması gereken kısım LEFT JOIN yapılırken sağdaki tabloda kayıtların olması yada olmaması durumunun ON clause bölümüne yazılırsa devam etmesidir. WHERE clause kısmına geçtiğinizde tablo çoktan birleştirilmiştir ve siz birleştirilmiş tablo üzerinde kesin filtreleme yapıyor olursunuz. Bu sebeple yaptığınız filtre direkt olarak satırları eleyecektir.
Yukarıdaki örneğin biraz daha düzgün hali (gerçek bir rapor formatına en yakın) aşağıdaki gibidir.
FROM firmam.urun AS u
LEFT JOIN firmam.satis AS s ON u.urun_id = s.urun_id
AND s.satis_tarih BETWEEN '2010-12-01 00:00:00' AND '2010-12-01 23:59:59'
WHERE 1
GROUP BY u.urun_id
RIGHT JOIN Kullanımı
MySQL RIGHT JOIN, LEFT JOIN işleminin tersini yapar. Yani seçilen tablolardan sağdaki bulunan tablonun tamamını alır ve soldaki tablodan da varsa eşleşen kayıtları alır yoksa NULL ile doldurulmuş kayıtlar döner.
İlk LEFT JOIN Örneğinin RIGHT JOIN ile Yazımı :
FROM firmam.musteri AS m
RIGHT JOIN firmam.musteri_detay AS md ON m.musteri_id = md.musteri_id
WHERE 1
Yukarıdaki örnekte 2 adet sorgu sonucu döndü. Bunun sebebi RIGHT JOIN kullandığınızda tabloların sağa birleştirilmesi. Sağdaki tablodaki (musteri_detay tablosu) tüm verileri (2 adet) alır ve sağdaki tablo ile soldaki (musteri) tablo arasındaki ortak veriler varsa alır yoksa NULL doldurur. Kaydı olmayan müşterinin detayı olamayacağı için soldaki tablo NULL ile doldurulmuş gelmez (tablodaki NULL olabilecek kolonlar hariç). Bu SQL başka bir deyişle müşteri detay bilgisi olan kayıtları getir demektir.
RIGHT JOIN ‘i LEFT JOIN gibi Kullanmak :
RIGHT JOIN ‘i LEFT JOIN ile karşılaştırmak istiyorsanız sorgunuzdaki tabloların yazım sırasını değiştirmemeniz gerekmektedir. Zira aşağıdaki örnek RIGHT JOIN kullanmamıza rağmen LEFT JOIN sonucunu döndürür.
FROM firmam.musteri_detay AS md
RIGHT JOIN firmam.musteri AS m ON md.musteri_id = m.musteri_id
WHERE 1
CROSS JOIN Kullanımı
MySQL CROSS JOIN, INNER JOIN ile aynı işlemi yapar.
MySQL JOIN İşlemlerinin Venn Şeması İle Gösterimi
MySQL FULL OUTER JOIN İşlemi (MySQL FULL OUTER JOIN desteklemez simülasyon ile yapıyoruz)
MySQL ile FULL OUTER JOIN kullanmak için union, union all yada mutex table yöntemini kullanmanız gerekir. (detaylar gelecek)
FULL OUTER JOIN için kullandığım kaynak: http://www.xaprb.com/blog/2006/05/26/how-to-write-full-outer-join-in-mysql/
İncelemenizde faydalı olabilecek ingilizce bir kaynak: http://www.guru99.com/sql.html
Kaynak