WordPress, yazılım ve IT üzerine notlar
Anasayfa » Yazılım » SQL JOIN türleri sade anlatım: INNER, LEFT, RIGHT ve sık yapılan hatalar

SQL JOIN türleri sade anlatım: INNER, LEFT, RIGHT ve sık yapılan hatalar

İçindekiler
  1. INNER JOIN: Yalnızca eşleşenler
  2. LEFT JOIN: Soldakilerin hepsi
  3. RIGHT JOIN: Sağdakilerin hepsi
  4. FULL OUTER JOIN
  5. Sık yapılan hatalar
  6. Hangi JOIN?

İlişkisel veritabanlarında veriler farklı tablolara bölünür: müşteriler bir tabloda, siparişler başka bir tabloda. Bir müşterinin siparişlerini ya da siparişleri veren müşterilerin adlarını görmek istediğinizde bu tabloları birleştirmeniz (JOIN) gerekir.

Örnek tablolarımız:

musteriler                    siparisler
+----+---------+              +----+-------------+--------+
| id | ad      |              | id | musteri_id  | tutar  |
+----+---------+              +----+-------------+--------+
|  1 | Ayşe    |              | 10 |      1      |  250   |
|  2 | Mehmet  |              | 11 |      1      |  120   |
|  3 | Zeynep  |              | 12 |      2      |  900   |
+----+---------+              | 13 |      9      |   75   |
                              +----+-------------+--------+

Dikkat edin: Zeynep'in hiç siparişi yok. 13 numaralı sipariş ise artık var olmayan 9 numaralı bir müşteriye ait (veri tutarsızlığı; gerçek hayatta da olur).

INNER JOIN: Yalnızca eşleşenler

SELECT m.ad, s.id AS siparis, s.tutar
FROM musteriler m
INNER JOIN siparisler s ON s.musteri_id = m.id;
Ayşe    10   250
Ayşe    11   120
Mehmet  12   900

Yalnızca her iki tabloda da karşılığı olan satırlar döner. Zeynep (siparişi yok) ve 13 numaralı sipariş (müşterisi yok) sonuçta görünmez. Yalnızca JOIN yazmak da INNER JOIN anlamına gelir.

LEFT JOIN: Soldakilerin hepsi

SELECT m.ad, s.id AS siparis, s.tutar
FROM musteriler m
LEFT JOIN siparisler s ON s.musteri_id = m.id;
Ayşe    10    250
Ayşe    11    120
Mehmet  12    900
Zeynep  NULL  NULL

Soldaki tablonun (musteriler) bütün satırları döner. Sağda karşılığı olmayanlar için sağ tablonun sütunları NULL olur.

LEFT JOIN'in en kullanışlı uygulamalarından biri, karşılığı olmayanları bulmaktır. Örneğin hiç sipariş vermemiş müşteriler:

SELECT m.ad
FROM musteriler m
LEFT JOIN siparisler s ON s.musteri_id = m.id
WHERE s.id IS NULL;
Zeynep

RIGHT JOIN: Sağdakilerin hepsi

SELECT m.ad, s.id AS siparis, s.tutar
FROM musteriler m
RIGHT JOIN siparisler s ON s.musteri_id = m.id;
Ayşe    10   250
Ayşe    11   120
Mehmet  12   900
NULL    13    75

LEFT JOIN'in tersidir. Pratikte pek kullanılmaz, çünkü tabloların yerini değiştirip LEFT JOIN yazmak daha okunaklıdır. Bu örnek, müşterisi silinmiş "yetim" siparişleri bulmak için işe yarar.

FULL OUTER JOIN

Her iki tablonun bütün satırlarını, eşleşmeyenleri de dahil ederek döndürür. PostgreSQL ve SQL Server destekler. MySQL ve MariaDB desteklemez; aynı sonucu LEFT JOIN ile RIGHT JOIN'i UNION ile birleştirerek elde edebilirsiniz.

Sık yapılan hatalar

1. LEFT JOIN'i WHERE ile INNER JOIN'e çevirmek

-- Amaç: Bütün müşteriler ve 2026'daki siparişleri
SELECT m.ad, s.tutar
FROM musteriler m
LEFT JOIN siparisler s ON s.musteri_id = m.id
WHERE s.tarih >= '2026-01-01';

Bu sorgu, 2026'da siparişi olmayan müşterileri sonuçtan çıkarır. Çünkü onlar için s.tarih değeri NULL olur ve WHERE koşulu sağlanmaz. LEFT JOIN, farkında olmadan INNER JOIN'e dönüşür.

Doğrusu, sağ tabloya ait koşulu ON kısmına yazmaktır:

SELECT m.ad, s.tutar
FROM musteriler m
LEFT JOIN siparisler s ON s.musteri_id = m.id AND s.tarih >= '2026-01-01';

Kural: LEFT JOIN'de sağ tabloyu filtreleyen koşullar ON'a, sol tabloyu filtreleyen koşullar WHERE'e yazılır.

2. Satırların katlanması

SELECT m.ad, SUM(s.tutar) AS toplam, COUNT(a.id) AS adres_sayisi
FROM musteriler m
LEFT JOIN siparisler s ON s.musteri_id = m.id
LEFT JOIN adresler   a ON a.musteri_id = m.id
GROUP BY m.id;

Ayşe'nin 2 siparişi ve 3 adresi varsa, birleştirme 2 × 3 = 6 satır üretir. Sipariş toplamı üç kat, adres sayısı iki kat fazla hesaplanır. Bu hata özellikle sinsidir, çünkü sorgu hata vermez; yalnızca yanlış sayılar döner.

Çözüm, toplamları ayrı ayrı hesaplayıp sonra birleştirmektir:

SELECT m.ad, s.toplam, a.adres_sayisi
FROM musteriler m
LEFT JOIN (SELECT musteri_id, SUM(tutar) toplam FROM siparisler GROUP BY musteri_id) s ON s.musteri_id = m.id
LEFT JOIN (SELECT musteri_id, COUNT(*) adres_sayisi FROM adresler GROUP BY musteri_id) a ON a.musteri_id = m.id;

3. ON koşulunu unutmak

ON koşulu eksik ya da yanlış yazılırsa, her satır diğer tablonun her satırıyla eşleşir (kartezyen çarpım). 10.000 müşteri ve 100.000 sipariş, bir milyar satır demektir. Sunucuyu kilitleyen sorguların klasik sebeplerinden biridir.

4. İndeks olmadan JOIN

ON s.musteri_id = m.id koşulundaki musteri_id sütununda indeks yoksa, veritabanı her müşteri için bütün sipariş tablosunu tarar. Yabancı anahtar sütunlarına her zaman indeks ekleyin. InnoDB, bir yabancı anahtar kısıtı tanımladığınızda bunu otomatik yapar.

Hangi JOIN?

  • Yalnızca ilişkisi olan kayıtlar → INNER JOIN
  • Ana tablonun bütün kayıtları, ilişkisi olsun olmasın → LEFT JOIN
  • Karşılığı olmayanları bulmak → LEFT JOIN + WHERE ... IS NULL

Yeni bir JOIN sorgusu yazdığınızda, sonucun satır sayısını mantıklı bir beklentiyle karşılaştırmayı alışkanlık hâline getirin. Beklediğinizden az satır kayıp kayıtları, fazla satır ise katlanmayı gösterir.

Tezcan Kabakçı
Hosting teknik destek uzmanı ve WordPress uzmanı. 2024'ten beri bir hosting şirketinde teknik destek bölümünde çalışıyor; WordPress, DNS ve e-posta sorunlarını her gün yakından görüyor. YouTube kanalı.
Bu yazı 23 Temmuz 2026 tarihinde Yazılım kategorisinde yayınlandı.
Yeni yazılar e-postanıza gelsin

Ayda birkaç e-posta; istediğiniz an tek tıkla ayrılabilirsiniz.

Videolu anlatımlar YouTube'da
Sunucu ve WordPress sorunlarını kısa videolarla anlattığım kanala abone olabilirsiniz. ▶ Kanala abone ol

Yorumlar

Henüz yorum yok. İlk yorumu siz yazın.

Yorum yazın

Yorumlar onaylandıktan sonra yayımlanır. Bağlantı içeren yorumlar spam olarak değerlendirilebilir.