SQL’de LEFT JOIN ve WHERE ilişkisi nedeniyle NULL kayıtlar çoğunlukla WHERE filtresinde elenir. LEFT JOIN, eşleşmeyen sol tablo satırlarını korur; ancak sağ tablodan gelen sütunları NULL olarak üretir. WHERE koşulu bu sağ tablo sütununu normal bir değerle karşılaştırdığında NULL satır koşulu sağlayamaz ve sonuçtan çıkar. Bu nedenle LEFT JOIN, JOIN türü değişmeden INNER JOIN gibi görünebilir.
LEFT JOIN Sonrasında WHERE Koşulu Satırları Neden Eler?
Bir müşterinin hiç siparişi yoksa LEFT JOIN bu müşteriyi sonuçta tutar. Örneğin sipariş tablosundan gelen sipariş_durumu sütunu, siparişi olmayan müşteri için NULL olur. Ancak aşağıdaki koşul yalnızca durumu “Tamamlandı” olan satırları kabul eder:
WHERE siparis.durum = 'Tamamlandı'
Buradaki kritik nokta, SQL’de NULL değerinin “normal bir değer” gibi karşılaştırılamamasıdır. NULL = 'Tamamlandı' ifadesi doğru veya yanlış yerine belirsiz sonuç üretir. WHERE aşaması yalnızca koşulu doğru olan satırları bıraktığı için bu kayıt sonuçtan çıkar.
Dolayısıyla sorun çoğu zaman LEFT JOIN’in çalışmaması değildir. Asıl neden, LEFT JOIN ile korunan eşleşmeyen satırların, sonradan sağ tablo sütununa uygulanan WHERE filtresi tarafından elenmesidir.
FROM/JOIN → ON → WHERE Sırasını Küçük Bir Örnekle İzleyin

Müşteri ve sipariş tablolarını şu küçük veri kümesiyle düşünelim:
| müşteriler | |
|---|---|
| müşteri_id | müşteri_adı |
| 1 | Ayşe |
| 2 | Bora |
| 3 | Cem |
| 4 | Deniz |
| siparişler | |
|---|---|
| müşteri_id | sipariş_durumu |
| 1 | Tamamlandı |
| 2 | Bekliyor |
| 4 | Tamamlandı |
Cem’in siparişi bulunmadığı için bu müşteri, LEFT JOIN sonrasında da sonuçta kalır. Mantıksal işlem sırasını üç adımda izleyebiliriz:
- FROM/JOIN: Müşteriler ile siparişler aynı sorgu kümesinde bir araya getirilir.
- ON:
müşteriler.müşteri_id = siparişler.müşteri_idkoşulu eşleşen siparişleri ilgili müşteriye bağlar. Cem için eşleşme bulunamadığından sipariş sütunu NULL olur. - WHERE: Sonuç kümesindeki satırlar ayrıca filtrelenir. Sağ tablo sütununa uygulanan koşul burada NULL satırını eleyebilir.
Yalnızca FROM/JOIN ve ON sonrasındaki ara sonuç şöyledir:
| müşteri_id | müşteri_adı | sipariş_durumu |
|---|---|---|
| 1 | Ayşe | Tamamlandı |
| 2 | Bora | Bekliyor |
| 3 | Cem | NULL |
| 4 | Deniz | Tamamlandı |
Bu aşamada beklenen kayıt sayısı 4tür; çünkü LEFT JOIN tüm müşterileri korur. Fakat filtre WHERE içine yazılırsa:
SELECT m.musteri_id, m.musteri_adi, s.durum AS siparis_durumu
FROM musteriler AS m
LEFT JOIN siparisler AS s
ON m.musteri_id = s.musteri_id
WHERE s.durum = 'Tamamlandı';
Sonuçta yalnızca Ayşe ve Deniz kalır; beklenen kayıt sayısı 2 olur. Bora’nın durumu “Bekliyor” olduğu için, Cem’in durumu ise NULL olduğu için WHERE koşulunu sağlayamaz. Böylece LEFT JOIN tarafından korunan eşleşmeyen müşteri satırı, WHERE aşamasında sonuçtan çıkarılmış olur.
Hatalı Sorgu ve İki Doğru Düzeltme Yöntemi
Örnek veri kümesinde üç müşteri bulunsun: Ayşe’nin “Tamamlandı” durumunda bir siparişi, Bora’nın “Beklemede” durumunda bir siparişi, Cem’in ise hiç siparişi yoktur. Amaç, müşterileri sipariş durumuna göre incelemektir.
| Müşteri | Sipariş durumu |
|---|---|
| Ayşe | Tamamlandı |
| Bora | Beklemede |
| Cem | NULL |
-- Hatalı: yalnızca 1 satır döner
SELECT c.ad, o.durum
FROM musteriler c
LEFT JOIN siparisler o ON o.musteri_id = c.id
WHERE o.durum = 'Tamamlandı';
-- Doğru 1: filtre ON koşulunda, 3 müşteri korunur
SELECT c.ad, o.durum
FROM musteriler c
LEFT JOIN siparisler o
ON o.musteri_id = c.id AND o.durum = 'Tamamlandı';
-- Doğru 2: siparişi olmayan müşteriyi açıkça seç
SELECT c.ad, o.durum
FROM musteriler c
LEFT JOIN siparisler o ON o.musteri_id = c.id
WHERE o.durum IS NULL;
Hatalı sorgu 1 satır döndürür: Ayşe. Çünkü Cem için üretilen NULL değer, “NULL = 'Tamamlandı'” karşılaştırmasında doğru kabul edilmez; Bora’nın durumu da filtreyi karşılamaz.
İlk düzeltmede filtre ON koşuluna taşınır. Böylece yalnızca “Tamamlandı” siparişler eşleştirilir, ancak eşleşme bulunamayan sol tablo satırları korunur. Sonuç 3 satırdır: Ayşe’nin sipariş durumu “Tamamlandı”, Bora ve Cem için sağ tablo sütunları NULL olur.
İkinci düzeltme, amacın siparişi olmayan müşterileri bulmak olduğu durum içindir. WHERE o.durum IS NULL yalnızca Cem’i döndürür; beklenen sonuç 1 satırdır. Tersine, siparişi bulunan müşterileri seçmek için WHERE o.durum IS NOT NULL kullanılabilir. Bu ifade Ayşe ve Bora’yı, yani 2 satırı döndürür.
Özetle, ON filtresi “hangi sağ tablo kayıtları eşleşsin?” sorusunu yanıtlar. WHERE içindeki IS NULL veya IS NOT NULL ise oluşan NULL durumu üzerinde bilinçli seçim yapar. Amaç eşleşmeyen müşterileri korumaksa sağ tablo filtresini doğrudan WHERE içine yazmadan önce bu farkı kontrol edin.
Eksik Kayıtları Teşhis Etmek İçin 4 Adımlı Kontrol Listesi

- Beklenen sol tablo satırlarını yazın. Kontrol sorusu: “Sonuçta tüm müşteriler görünmeli mi?” Beklenen gözlem, LEFT JOIN kullanılıyorsa sol tablodaki satırların korunmasıdır.
- ON koşulunu inceleyin. Kontrol sorusu: “Eşleşme hangi anahtar ve şartlarla kuruluyor?” Müşteri kimliği gibi bağlantı koşullarını ve ek durum filtrelerini ayrı ayrı değerlendirin.
- NULL oluşan satırları işaretleyin. Kontrol sorusu: “Eşleşmeyen müşterinin sağ tablo sütunlarında ne var?” Beklenen cevap NULL’dur; bu değer boş metin veya sıfır anlamına gelmez.
- WHERE koşullarını tek tek uygulayın. Kontrol sorusu: “Bu koşul NULL taşıyan satırı koruyor mu?” NULL, normal bir değer gibi eşitlik karşılaştırmasına girmez; bu nedenle açıkça
IS NULLveyaIS NOT NULLile ele alınmalıdır.
- WHERE içinde sağ tabloya ait bir filtre var mı?
- Bu filtre eşleşmeyen kayıtları da korumalı mı?
- NULL durumu sorguda açıkça ele alındı mı?
Bu teşhis akışı, aslında koşulların hangi sırayla değerlendirildiğini düşünme pratiğidir. Benzer koşullu düşünme becerilerini geliştirmek isteyenler, algoritma bilgi testi ile kendi mantık kurma düzeylerini sınayabilir.
Hangi Durumda INNER JOIN, Hangi Durumda ON Filtresi Kullanılır?
Karar vermek için önce şu soruyu sorun: Eşleşmeyen sol tablo kayıtları sonuçta mutlaka kalmalı mı?
- Hayır: Yalnızca ilişkili kayıtlar isteniyorsa
INNER JOINdaha açık bir tercihtir. Eşleşmeyen müşteriler sonuçtan bilinçli olarak çıkarılır. - Evet: Sol tablodaki tüm kayıtlar korunacaksa sağ tabloya ait filtre çoğu durumda
ONkoşuluna taşınmalıdır. Böylece filtreye uymayan sağ kayıt eşleşmemiş kabul edilir, ancak sol kayıt kaybolmaz. - Yalnızca eşleşmeyen kayıtlar aranıyorsa:
LEFT JOINsonrasındaWHERE sag_tablo.id IS NULLkullanılır. Bu yaklaşım, sağ tabloda karşılığı bulunmayan kayıtları seçer.
Örneğin yalnızca siparişi olan müşterileri listelemek istiyorsanız INNER JOIN kullanabilirsiniz. Tüm müşterileri gösterip yalnızca tamamlanmış siparişleri ilişkilendirmek istiyorsanız durum farklıdır:
SELECT m.id, m.ad
FROM musteriler AS m
LEFT JOIN siparisler AS s
ON s.musteri_id = m.id
AND s.durum = 'Tamamlandı';
Bu sorguda tamamlanmış siparişi olmayan müşteriler yine listede kalır; sipariş sütunları NULL olur. Amaç tamamlanmış siparişi olmayan müşterileri bulmaksa sorguya WHERE s.id IS NULL eklenir. Sorguyu değiştirmeden önce mevcut sonucu “tüm müşteriler”, “en az bir siparişi olanlar” veya “hiç siparişi olmayanlar” gruplarından hangisiyle karşılaştıracağınızı netleştirin.
Sorguyu Çalıştırmadan Önce NULL Kayıp Kontrolü
Gerçek bir projede müşteri-sipariş sorgusunu değiştirirken önce filtrelenen sütunun hangi tabloya ait olduğunu belirleyin. Sütun sağ tablodan geliyorsa, eşleşmeyen sol tablo satırlarında bu sütunun NULL olacağını hatırlayın. Ardından aynı koşulu önce ON, sonra WHERE içinde deneyerek ara sonuçları karşılaştırın.
“Siparişi olmayan müşteriler” ile “tamamlanmış siparişi olan müşteriler” aynı sorgu biçimiyle çözülmez:
-- Siparişi olmayan müşteriler
SELECT m.id, m.ad
FROM musteriler AS m
LEFT JOIN siparisler AS s
ON s.musteri_id = m.id
WHERE s.id IS NULL;
-- Tamamlanmış siparişi olan müşteriler
SELECT DISTINCT m.id, m.ad
FROM musteriler AS m
INNER JOIN siparisler AS s
ON s.musteri_id = m.id
WHERE s.durum = 'Tamamlandı';
İlk sorgunun beklenen sonucu, hiç siparişi bulunmayan müşteriler grubudur. İkinci sorgu ise en az bir tamamlanmış siparişi olan müşterileri döndürür; bu nedenle aynı müşteri birden fazla siparişe sahipse DISTINCT tekrarları engeller. Son kontrol olarak beklediğiniz müşteri listesini sorgu çıktısıyla tek tek karşılaştırın. Sorgu mantığını ve temel programlama düşüncesini pekiştirmek için programlama mantığı odaklı video eğitimler de yardımcı olabilir.
Sık Sorulan Sorular
LEFT JOIN neden bazı durumlarda INNER JOIN gibi davranır?
Sağ tabloya ait sütun üzerinde WHERE koşulu kullanıldığında, eşleşmeyen satırlardaki NULL değerler koşulu sağlayamaz ve sonuçtan elenir. Böylece yalnızca eşleşen kayıtlar kalır.
LEFT JOIN içinde sağ tabloya ait filtre ON koşuluna mı, WHERE koşuluna mı yazılmalı?
Sol tablodaki tüm kayıtları korumak istiyorsanız filtreyi genellikle ON koşuluna yazın. Filtreye uymayan sağ kayıtlar elenir, ancak sol tablodaki müşteri satırı korunur.
LEFT JOIN ile eşleşmeyen kayıtları nasıl bulabilirim?
Sağ tablonun kesinlikle dolu olması gereken bir kimlik sütununu seçip WHERE sag_tablo.id IS NULL koşulunu kullanabilirsiniz.
WHERE koşulunda NULL değerler neden eşitlik karşılaştırmasını sağlamaz?
NULL, belirli bir değer değil bilinmeyen veya mevcut olmayan değerdir. Bu nedenle NULL = NULL ifadesi doğru kabul edilmez; kontrol için IS NULL kullanılmalıdır.
IS NULL ile IS NOT NULL arasındaki kullanım farkı nedir?
IS NULL değeri bulunmayan kayıtları, IS NOT NULL ise değeri bulunan kayıtları seçer. Eşleşmeyen kayıt analizi genellikle IS NULL ile yapılır.
Doğru sorgu biçimi, JOIN türünden çok ulaşmak istediğiniz kayıt grubuna göre seçilmelidir: tüm sol kayıtları korumak, yalnızca eşleşenleri almak veya eşleşmeyenleri ayıklamak farklı amaçlardır.