SQL JOIN Türleri Nelerdir? INNER, LEFT ve RIGHT JOIN Örnekleri
İçindekiler
- Kısa Özet
- JOIN neden gereklidir?
- Örnek tablolar nasıl hazırlanır?
- INNER JOIN nedir ve nasıl kullanılır?
- LEFT JOIN nedir ve ne zaman kullanılır?
- RIGHT JOIN nedir?
- FULL OUTER JOIN nasıl çalışır?
- MySQL üzerinde FULL OUTER JOIN nasıl yapılır?
- CROSS JOIN ne işe yarar?
- SELF JOIN nedir?
- Üç veya daha fazla tablo nasıl birleştirilir?
- JOIN kullanırken en sık yapılan hatalar nelerdir?
- LEFT JOIN sonrası WHERE ile filtreleme
- ON koşulunu unutmak
- Aynı isimli sütunları ayırmamak
- İndeks olmadan büyük tabloları birleştirmek
- Sahada JOIN hangi problemleri çözüyor?
- Hangi JOIN türünü seçmeliyim?
SQL JOIN, iki veya daha fazla tabloyu ortak bir sütun üzerinden birleştirip tek bir sonuç listesi olarak getiren komuttur. En sık kullanılan türler INNER JOIN, LEFT JOIN, RIGHT JOIN, FULL OUTER JOIN ve CROSS JOIN'dir. Aralarındaki temel fark, eşleşmeyen kayıtların sonuca dahil edilip edilmemesidir.
Bu yazıda her JOIN türünü aynı iki örnek tablo üzerinde çalıştırıp sonuçlarını karşılaştırmalı olarak göstereceğim. Böylece hangi sorgunun hangi satırları getirdiğini ezberlemeden, mantığını görerek öğreneceksiniz. Tablolar arası ilişkilerin temelini oluşturan anahtar kavramları için sitemizdeki Key, Primary Key, Unique Key ve Foreign Key Tanımlamaları yazısına da bakabilirsiniz.
Kısa Özet
- INNER JOIN: Yalnızca iki tabloda da eşleşen kayıtlar gelir.
- LEFT JOIN: Sol tablonun tüm kayıtları gelir, sağda eşleşme yoksa NULL yazılır.
- RIGHT JOIN: Sağ tablonun tüm kayıtları gelir, solda eşleşme yoksa NULL yazılır.
- FULL OUTER JOIN: İki tablonun tüm kayıtları gelir, eşleşmeyen taraflar NULL olur.
- CROSS JOIN: Her satır diğer tablonun her satırıyla birleşir.
- SELF JOIN: Tablo kendisiyle birleştirilir, hiyerarşik veriler için kullanılır.
JOIN neden gereklidir?
İyi tasarlanmış bir veritabanında bilgiler tekrar edilmemek için farklı tablolara bölünür. Örneğin personelin departman adı her personel satırına tek tek yazılmaz; departmanlar ayrı bir tabloda tutulur ve personel tablosunda yalnızca departmanın numarası saklanır.
Bu yapı veri tekrarını önler ve güncellemeyi kolaylaştırır. Ancak rapor alırken personelin adını ve departmanının adını yan yana görmek istediğinizde iki tabloyu birleştirmeniz gerekir. İşte bu birleştirme işini JOIN yapar.
Örnek tablolar nasıl hazırlanır?
Tüm örneklerde aşağıdaki iki tabloyu kullanacağız. Kodlar hem SQLite hem de MySQL üzerinde çalışır.
CREATE TABLE departmanlar (
id INTEGER PRIMARY KEY,
ad VARCHAR(50) NOT NULL
);
CREATE TABLE personel (
id INTEGER PRIMARY KEY,
ad VARCHAR(50) NOT NULL,
departman_id INTEGER,
FOREIGN KEY (departman_id) REFERENCES departmanlar(id)
);
INSERT INTO departmanlar (id, ad) VALUES
(1, 'Üretim'), (2, 'Muhasebe'), (3, 'Bilgi İşlem'), (4, 'Satış');
INSERT INTO personel (id, ad, departman_id) VALUES
(1, 'Ahmet', 1), (2, 'Ayşe', 2), (3, 'Mehmet', 1),
(4, 'Elif', NULL), (5, 'Can', 3);
Dikkat ederseniz iki bilinçli boşluk bıraktık: Elif henüz bir departmana atanmamış, Satış departmanında ise hiç personel yok. JOIN türlerinin farkı tam da bu iki kayıtta ortaya çıkacak.
INNER JOIN nedir ve nasıl kullanılır?
INNER JOIN, iki tabloda da karşılığı olan kayıtları getirir. Eşleşmesi olmayan satırlar sonuçtan tamamen çıkarılır. JOIN yazıp tür belirtmezseniz veritabanı bunu INNER JOIN olarak yorumlar.
SELECT p.ad AS personel, d.ad AS departman
FROM personel p
INNER JOIN departmanlar d ON p.departman_id = d.id;
| personel | departman |
|---|---|
| Ahmet | Üretim |
| Ayşe | Muhasebe |
| Mehmet | Üretim |
| Can | Bilgi İşlem |
Sonuçta 4 satır var. Departmanı olmayan Elif ve personeli olmayan Satış departmanı listeye girmedi. Fatura ile müşteri, sipariş ile ürün gibi karşılığı mutlaka olması gereken ilişkilerde INNER JOIN doğru seçimdir.
LEFT JOIN nedir ve ne zaman kullanılır?
LEFT JOIN, FROM ifadesinden sonra yazılan sol tablonun tüm kayıtlarını getirir. Sağ tabloda eşleşme bulunmazsa o sütunlar NULL olarak döner.
SELECT p.ad AS personel, d.ad AS departman
FROM personel p
LEFT JOIN departmanlar d ON p.departman_id = d.id;
| personel | departman |
|---|---|
| Ahmet | Üretim |
| Ayşe | Muhasebe |
| Mehmet | Üretim |
| Elif | NULL |
| Can | Bilgi İşlem |
Bu kez Elif de listede, ancak departmanı NULL. LEFT JOIN özellikle eksik kayıtları bulmak için çok kullanışlıdır. Aşağıdaki sorgu departmanı atanmamış personeli listeler:
SELECT p.ad
FROM personel p
LEFT JOIN departmanlar d ON p.departman_id = d.id
WHERE d.id IS NULL;
RIGHT JOIN nedir?
RIGHT JOIN, LEFT JOIN'in ayna görüntüsüdür. Sağ tablonun tüm kayıtları gelir, sol tabloda karşılığı yoksa sol sütunlar NULL olur.
SELECT p.ad AS personel, d.ad AS departman
FROM personel p
RIGHT JOIN departmanlar d ON p.departman_id = d.id;
| personel | departman |
|---|---|
| Ahmet | Üretim |
| Mehmet | Üretim |
| Ayşe | Muhasebe |
| Can | Bilgi İşlem |
| NULL | Satış |
Pratikte RIGHT JOIN çok az kullanılır, çünkü tabloların yerini değiştirip LEFT JOIN yazmak aynı sonucu verir ve okunması daha kolaydır. Ekip içinde tek bir alışkanlık belirlemek sorguların bakımını kolaylaştırır; ben tüm projelerimde yalnızca LEFT JOIN kullanıyorum.
FULL OUTER JOIN nasıl çalışır?
FULL OUTER JOIN, iki tablonun tüm kayıtlarını getirir. Eşleşen satırlar yan yana gelir, eşleşmeyenlerin karşı tarafı NULL olur. Örneğimizde sonuç 6 satırdır: 4 eşleşen kayıt, Elif ve Satış departmanı.
SELECT p.ad AS personel, d.ad AS departman
FROM personel p
FULL OUTER JOIN departmanlar d ON p.departman_id = d.id;
MySQL üzerinde FULL OUTER JOIN nasıl yapılır?
MySQL, FULL OUTER JOIN sözdizimini desteklemez. Aynı sonucu LEFT JOIN ve RIGHT JOIN sorgularını UNION ile birleştirerek elde edebilirsiniz. UNION tekrar eden satırları otomatik olarak eler.
SELECT p.ad AS personel, d.ad AS departman
FROM personel p
LEFT JOIN departmanlar d ON p.departman_id = d.id
UNION
SELECT p.ad AS personel, d.ad AS departman
FROM personel p
RIGHT JOIN departmanlar d ON p.departman_id = d.id;
SQLite tarafında ise RIGHT JOIN ve FULL OUTER JOIN desteği 3.39.0 sürümüyle geldi. Eski bir SQLite sürümü kullanıyorsanız bu sorgular hata verir; aynı UNION yöntemini burada da kullanabilirsiniz.
CROSS JOIN ne işe yarar?
CROSS JOIN, bir tablonun her satırını diğer tablonun her satırıyla eşleştirir. Bu işleme kartezyen çarpım denir. Örneğimizde 5 personel ve 4 departman olduğu için sonuç 20 satırdır.
SELECT p.ad, d.ad
FROM personel p
CROSS JOIN departmanlar d;
CROSS JOIN seyrek kullanılır ama belirli durumlarda çok işe yarar. Örneğin tüm ürünlerin tüm bedenlerle kombinasyonunu üretmek veya her personel için her günün boş bir vardiya satırını oluşturmak gibi. Büyük tablolarda yanlışlıkla çalıştırılırsa milyonlarca satır üretebileceğini unutmayın.
SELF JOIN nedir?
SELF JOIN, bir tablonun kendisiyle birleştirilmesidir. Ayrı bir anahtar kelimesi yoktur; aynı tabloya iki farklı takma ad verilerek yazılır. Personel ile yöneticisinin aynı tabloda tutulduğu yapılar tipik örnektir.
ALTER TABLE personel ADD COLUMN yonetici_id INTEGER;
SELECT calisan.ad AS personel, yonetici.ad AS yonetici
FROM personel calisan
LEFT JOIN personel yonetici ON calisan.yonetici_id = yonetici.id;
Üç veya daha fazla tablo nasıl birleştirilir?
JOIN ifadeleri art arda yazılabilir. Her yeni JOIN, önceki birleştirmenin sonucuna eklenir. Örneğin personelin giriş kayıtlarını departman bilgisiyle birlikte listelemek için:
SELECT p.ad, d.ad AS departman, g.giris_zamani
FROM giris_kayitlari g
INNER JOIN personel p ON g.personel_id = p.id
LEFT JOIN departmanlar d ON p.departman_id = d.id
ORDER BY g.giris_zamani DESC;
JOIN kullanırken en sık yapılan hatalar nelerdir?
LEFT JOIN sonrası WHERE ile filtreleme
LEFT JOIN yazıp sağ tabloya ait bir koşulu WHERE içine koyarsanız, NULL gelen satırlar elenir ve sorgu fiilen INNER JOIN gibi davranır. Sağ tabloya ait filtreyi ON ifadesinin içine yazmak gerekir.
-- Hatalı: Elif listeden düşer
SELECT p.ad, d.ad
FROM personel p
LEFT JOIN departmanlar d ON p.departman_id = d.id
WHERE d.ad = 'Üretim';
-- Doğru: tüm personel gelir, yalnızca Üretim departmanı eşleşir
SELECT p.ad, d.ad
FROM personel p
LEFT JOIN departmanlar d ON p.departman_id = d.id AND d.ad = 'Üretim';
ON koşulunu unutmak
Bazı veritabanları ON koşulu yazılmayan JOIN ifadesini CROSS JOIN gibi çalıştırır. Sonuçta beklenmedik şekilde çok sayıda satır görüyorsanız ilk kontrol edeceğiniz yer ON koşuludur.
Aynı isimli sütunları ayırmamak
İki tabloda da ad veya id sütunu varsa, SELECT içinde hangi tablonun sütununu istediğinizi takma adla belirtmelisiniz. Aksi halde belirsiz sütun hatası alırsınız veya PHP tarafında dizi anahtarları birbirinin üzerine yazılır.
İndeks olmadan büyük tabloları birleştirmek
JOIN koşulunda kullanılan sütunlarda indeks yoksa veritabanı her satır için tüm tabloyu tarar. Primary key sütunları otomatik indekslenir, ancak departman_id gibi foreign key sütunlarına indeksi çoğu zaman sizin eklemeniz gerekir.
CREATE INDEX idx_personel_departman ON personel(departman_id);
Sahada JOIN hangi problemleri çözüyor?
Kart okuyuculu giriş çıkış sistemlerinden alınan kayıtlarla çalışırken LEFT JOIN'in ne kadar değerli olduğunu defalarca gördüm. Cihazdan gelen okuma kayıtlarını personel tablosuyla LEFT JOIN ile birleştirip personel adı NULL gelenleri listelediğimde, sisteme tanımlanmamış veya iptal edilmiş kartlarla yapılan okumaları birkaç saniyede buldum.
Benzer şekilde stok takibinde ürün tablosunu hareket tablosuyla LEFT JOIN yapıp hareket sayısı sıfır olanları filtrelemek, uzun süredir kullanılmayan kalemleri tespit etmenin en hızlı yoludur. Bu tür kontrol sorgularını kaydedip düzenli aralıklarla çalıştırmak veri kalitesini ciddi şekilde artırır.
Hangi JOIN türünü seçmeliyim?
| İhtiyaç | Önerilen JOIN |
|---|---|
| Yalnızca eşleşen kayıtlar | INNER JOIN |
| Ana tablonun tamamı, ek bilgi varsa göster | LEFT JOIN |
| Eşleşmesi olmayan kayıtları bulmak | LEFT JOIN ve WHERE sütun IS NULL |
| İki tarafın tüm kayıtları | FULL OUTER JOIN veya UNION |
| Tüm kombinasyonlar | CROSS JOIN |
| Aynı tablodaki hiyerarşi | SELF JOIN |

0 Yorum