Berk Akademi
Birebir ders başvurusu Ücretsiz ön görüşme Ana Sayfa

Subquery returns more than one row Hatası ve Doğru Sorgu Seçimi

subquery-returns-more-than-one-row-hatasi
Bu yazıda neler var?
  1. Subquery returns more than one row hatası neden oluşur?
  2. Hatalı alt sorgu adım adım nasıl teşhis edilir?
  3. Tek değer gerekiyorsa MAX veya MIN ne zaman kullanılmalı?
  4. IN, EXISTS ve JOIN hangi sonuç ihtiyacında seçilir?
  5. Son sipariş kaydı JOIN ile nasıl bulunur?
  6. Doğru SQL yaklaşımını seçmek için karar ağacı
  7. Sık Sorulan Sorular

“Subquery returns more than one row” hatası, tek bir değer beklenen yerde alt sorgunun birden fazla satır döndürmesiyle oluşur. Çözüm, alt sorguyu zorla tek satıra indirmek değil; sorgunun gerçekten tek değer mi, birden fazla değer mi yoksa yalnızca kayıt varlığı mı aradığını belirleyip buna uygun SQL yapısını seçmektir.

Örneğin müşterinin son sipariş tarihini ararken, her müşterinin birden fazla siparişi olabileceği unutulursa = operatörüyle kullanılan korelasyonlu alt sorgu hata verebilir. Önce hatanın mantığını, ardından hangi satırda oluştuğunu incelemek gerekir.

Subquery returns more than one row hatası neden oluşur?

Scalar subquery, çevresindeki sorguda bir sütun veya tek bir değer beklenen bağlamda kullanılan alt sorgudur. Böyle bir alt sorgunun normal şartlarda tek sütun ve en fazla bir satır üretmesi beklenir. Örneğin aşağıdaki yapı, customer_id değerinin tek bir sonuçla karşılaştırılacağını varsayar:

SELECT *
FROM customers
WHERE customer_id = (
    SELECT customer_id
    FROM orders
);

orders tablosunda birden fazla sipariş varsa alt sorgu da birden fazla customer_id döndürebilir. Ancak = operatörünün sağ tarafında tek bir değer beklenmektedir. Bir değeri aynı anda iki veya daha fazla farklı satırla doğrudan eşleştirmek belirsiz olduğu için sorgu motoru hata üretir.

MySQL’de bu hata kalıbı genellikle ERROR 1242 (ER_SUBSELECT_NO_1_ROW) ve Subquery returns more than 1 row mesajıyla görülür. Başka sorgu motorlarında hata metni değişebilir; bu nedenle makaledeki ifade, belirli bir hata kalıbını tanımlamak için kullanılmaktadır. MySQL dokümantasyonuna göre scalar alt sorgu hiç satır döndürmezse sonuç NULL olabilir; bir satır döndürürse o değer kullanılır, birden fazla satır döndürürse hata oluşur.

  • Sıfır satır: Alt sorgu eşleşme bulamaz. Scalar bağlamda sonuç, kullanılan motorun davranışına bağlı olarak çoğunlukla NULL olur.
  • Tek satır: Alt sorgu beklenen biçimde tek değer üretir ve = gibi operatörlerle kullanılabilir.
  • Birden fazla satır: Tek değer bekleyen scalar bağlam bozulur ve “Subquery returns more than one row” türünde hata oluşur.

Hatalı alt sorgu adım adım nasıl teşhis edilir?

Hatalı alt sorgu adım adım nasıl teşhis edilir?

Amaç, her müşterinin son sipariş tarihini bulmak olsun. Aşağıdaki sorgu ilk bakışta doğru görünebilir; ancak alt sorgu müşterinin tüm sipariş tarihlerini döndürür:

SELECT
    c.customer_id,
    c.customer_name,
    o.order_date
FROM customers AS c
JOIN orders AS o
    ON o.customer_id = c.customer_id
WHERE o.order_date = (
    SELECT o2.order_date
    FROM orders AS o2
    WHERE o2.customer_id = c.customer_id
);

Örneğin customer_id = 1 olan müşterinin 2026-08-10 ve 2026-09-01 tarihli iki siparişi varsa, korelasyonlu alt sorgunun beklenen ara çıktısı iki satırdır:

2026-08-10
2026-09-01

Oysa dış sorgudaki = operatörü tek bir tarih bekler. Hatanın kaynağını bulmak için şu kontrol listesini uygula:

  1. Alt sorguyu dış sorgudan ayırıp bağımsız çalıştır.
  2. customer_id gibi korelasyon filtrelerinin doğru tablo ve takma adları kullandığını kontrol et.
  3. Aynı müşteri için kaç sipariş bulunduğunu COUNT(*) ile say.
  4. Beklenen sonucun tek tarih, tarih listesi veya yalnızca “siparişi var mı?” bilgisi olup olmadığına karar ver.

Bu adımlar, yalnızca SQL sözdizimini değil, problemi parçalara ayırma becerisini de geliştirir. SQL testi sunmayan; Python, Java, C# ve algoritmik düşünme alanlarında ücretsiz değerlendirmeler içeren ücretsiz bilgi ve algoritmik düşünme değerlendirmeleri bu bakış açısını çalışmak isteyenler için doğal bir başlangıç olabilir.

Tek değer gerekiyorsa MAX veya MIN ne zaman kullanılmalı?

Alt sorgunun dış sorguya tek bir değer döndürmesi gerekiyorsa MAX() veya MIN() kullanılabilir. Örneğin amaç, her müşterinin yalnızca son sipariş tarihini bulmaksa orders.order_date sütunu üzerinde MAX() çalıştırmak uygun bir çözümdür:

SELECT
    c.customer_id,
    c.customer_name,
    (
        SELECT MAX(o.order_date)
        FROM orders AS o
        WHERE o.customer_id = c.customer_id
    ) AS last_order_date
FROM customers AS c;

Bu korelasyonlu alt sorgu, her müşteri için orders tablosundaki tarihleri ayrı ayrı değerlendirir ve en büyük tarihi üretir. Sonuçta her müşteri için yalnızca bir satır bulunur. Örneğin sonuç şu yapıda olabilir:

customer_id | customer_name | last_order_date
------------+---------------+----------------
1           | Ayşe          | 2026-08-21
2           | Mehmet        | 2026-08-30
3           | Zeynep        | NULL

Zeynep’in siparişi yoksa MAX() değeri NULL olur; müşteri yine de dış sorguda listelenir. Aynı tarihte birden fazla sipariş varsa sonuç yine tek bir tarih üretir. Ancak bu sorgu yalnızca tarihi bulur; son siparişin order_id, ürün veya tutar gibi diğer sütunlarını aynı yöntemle güvenilir biçimde getirmez. Bu ayrıntıların tamamı gerekiyorsa alt sorgu yerine uygun bir JOIN yaklaşımı gerekir.

MIN() ise aynı mantıkla en eski sipariş tarihini bulmak için kullanılır:

SELECT
    c.customer_id,
    c.customer_name,
    (
        SELECT MIN(o.order_date)
        FROM orders AS o
        WHERE o.customer_id = c.customer_id
    ) AS first_order_date
FROM customers AS c;

Birden fazla müşteriyi veya siparişi müşteri bazında özetlemek istediğinde GROUP BY de kullanılabilir:

SELECT
    customer_id,
    MAX(order_date) AS last_order_date
FROM orders
GROUP BY customer_id;

Bu sorgu yalnızca siparişi bulunan müşterileri döndürür; siparişi olmayan müşteriler sonuçta yer almaz. Ayrıca aggregate fonksiyonu rastgele bir satır seçmez. Belirli bir sütun üzerinde hesap yaparak o grubun en büyük, en küçük veya başka bir özet değerini üretir.

IN, EXISTS ve JOIN hangi sonuç ihtiyacında seçilir?

IN, EXISTS ve JOIN hangi sonuç ihtiyacında seçilir?

IN, bir değerin alt sorgudan dönen değerler kümesinin içinde olup olmadığını denetlemek için kullanılır. Örneğin siparişi bulunan müşterilerin kimliklerini filtrelemek için:

SELECT customer_id, customer_name
FROM customers
WHERE customer_id IN (
    SELECT customer_id
    FROM orders
);

Beklenen sonuç, en az bir siparişi bulunan müşterilerin kimlik ve ad bilgileridir. Burada amaç sipariş ayrıntılarını listelemek değil, müşterinin kimlik değerinin belirli bir kümede bulunup bulunmadığını kontrol etmektir.

EXISTS ise ilişkili bir kaydın varlığını denetlemek için tercih edilir:

SELECT c.customer_id, c.customer_name
FROM customers AS c
WHERE EXISTS (
    SELECT 1
    FROM orders AS o
    WHERE o.customer_id = c.customer_id
);

Bu sorgu da en az bir siparişi olan müşterileri döndürür. Siparişin hangi ürün olduğu veya kaç sipariş bulunduğu sonuçta gösterilmez; yalnızca ilişkili bir sipariş kaydının varlığı önemlidir.

İki tablodan sütunları aynı sonuçta birleştirmek istiyorsan JOIN kullanılır:

SELECT
    c.customer_name,
    o.order_id,
    o.order_date
FROM customers AS c
INNER JOIN orders AS o
    ON o.customer_id = c.customer_id;

Beklenen sonuçta müşteri adıyla birlikte sipariş kimliği ve tarihi listelenir. Bir müşterinin üç siparişi varsa o müşteri sonuçta üç satırda görünebilir. INNER JOIN yalnızca eşleşen kayıtları getirirken LEFT JOIN, siparişi olmayan müşterileri de korur ve sipariş sütunlarında NULL gösterir. Bu nedenle seçim, üyelik kontrolü mü, kayıt varlığı mı, yoksa iki tablonun ayrıntılarını birleştirme mi istediğine göre yapılmalıdır.

Son sipariş kaydı JOIN ile nasıl bulunur?

MAX(order_date) yalnızca en yüksek tarihi üretir; o siparişe ait order_id ve total_amount gibi sütunları kendiliğinden getirmez. Tam kayda ulaşmak için önce müşteri bazında son tarihi hesaplayabilir, ardından bu sonucu orders tablosuyla eşleştirebilirsin.

SELECT
    c.customer_id,
    c.customer_name,
    o.order_id,
    o.order_date,
    o.total_amount
FROM customers AS c
JOIN (
    SELECT
        customer_id,
        MAX(order_date) AS last_order_date
    FROM orders
    GROUP BY customer_id
) AS latest
    ON latest.customer_id = c.customer_id
JOIN orders AS o
    ON o.customer_id = latest.customer_id
   AND o.order_date = latest.last_order_date
ORDER BY c.customer_id, o.order_id;

Türetilmiş tablo her customer_id için son sipariş tarihini bulur. İkinci JOIN ise aynı müşteriye ve tarihe ait sipariş kaydını getirir. Böylece beklenen sonuçta müşterinin son sipariş tarihiyle birlikte sipariş kimliği ve toplam tutarı da yer alır.

Bir müşterinin en yüksek tarihte iki siparişi bulunuyorsa sonuçta iki satır oluşur. Örneğin 7 numaralı müşterinin aynı gün içinde 104 ve 108 numaralı siparişleri varsa ikisi de eşleşir. Bu bir sorgu hatası değil, “son tarihle eşleşen bütün kayıtları getir” kuralının doğal sonucudur.

Korelasyonlu alt sorgu da o.order_date = (SELECT MAX(...)) koşuluyla aynı eşitlik durumunda birden fazla kayıt döndürebilir. GROUP BY yalnızca özet tarih isteniyorsa yeterlidir; kaydın diğer sütunları gerekiyorsa JOIN veya başka bir kayıt seçme yöntemi gerekir. Sonucun tek satır olması zorunluysa veri modelinde tarihin müşteri başına benzersiz olup olmadığını ve eşitlik durumunda hangi siparişin seçileceğini açıkça belirlemelisin.

  • MAX(order_date) ile MAX(order_id) değerlerini bağımsız hesaplayıp aynı siparişe ait olduklarını varsayma.
  • Önce “son sipariş” tanımının yalnız tarihe mi, yoksa tarih ve sipariş kimliği gibi bir eşitlik bozucuya mı dayandığını belirle.
  • Birden fazla eşleşmenin geçerli bir sonuç mu, yoksa iş kuralına aykırı bir veri durumu mu olduğunu kontrol et.

Doğru SQL yaklaşımını seçmek için karar ağacı

  1. Tek bir özet değer mi gerekiyor? En yüksek tarih veya en düşük tutar gibi bir sonuç için MAX ya da MIN kullan.
  2. Bir değer kümesiyle üyelik karşılaştırması mı yapıyorsun? Alt sorgunun döndürdüğü değerlerden herhangi biriyle eşleşmek için IN seçeneğini değerlendir.
  3. Yalnızca ilişkili kayıt bulunup bulunmadığını mı kontrol ediyorsun? Sonuç sütunlarını taşımak yerine varlık koşulunu ifade eden EXISTS kullan.
  4. İlişkili tablodan ek sütunlar mı gerekiyor? Müşteriyle birlikte sipariş kimliği ve tutarı gibi alanları almak için uygun JOIN türünü seç.
Yaklaşım Hangi durumda kullanılır? Ürettiği sonuç Temel risk
MAX/MIN Tek özet değer gerektiğinde Bir değer Tam kayıt sanılması
IN Bir değer kümesiyle karşılaştırmada Eşleşen kayıtlar NULL davranışının gözden kaçması
EXISTS Varlık kontrolünde Koşulu sağlayan dış kayıtlar Ek sütun getireceğinin sanılması
JOIN Tabloların sütunları birlikte gerektiğinde Birleştirilmiş kayıtlar Çoklu eşleşmeyle satır çoğalması

Dört soruluk kontrol listesi

Hangi seçeneği değerlendirirsen değerlendir şu dört soruyu uygula: Beklenen satır sayısı nedir? Tam kayıt mı, özet değer mi gerekir? Eşleşmeyen kayıtlar korunacak mı? Birden fazla eşleşme sonucu çoğaltabilir mi? Bu sorular özellikle JOIN türünü ve tek satır beklentisinin gerçekten geçerli olup olmadığını netleştirir.

LIMIT, TOP veya FETCH FIRST gibi satır sınırlama biçimleri sorgu motoruna göre değişir. Bunları yalnız açık bir sıralama kuralı varsa düşünmelisin. Sıralama eşit değerler üretiyorsa benzersiz bir ikinci ölçüt eklenmediği sürece seçilecek satır belirli olmayabilir; bazı motorlarda eşit sıralama değerlerini kapsayan ek seçenekler de bulunur.

SQL dışında farklı yazılım konularını kendi hızında çalışmak istersen asenkron video eğitim seçeneklerini inceleyebilirsin.

Sık Sorulan Sorular

Alt sorguya LIMIT 1 eklemek hatayı kalıcı olarak çözer mi?

Her zaman çözmez. Yalnızca bir satır seçerek hata mesajını ortadan kaldırabilir; ancak hangi satırın seçileceğini tanımlayan deterministik bir ORDER BY yoksa sonuç iş kuralını karşılamayabilir.

MAX(order_date) müşterinin son sipariş kaydının tamamını getirir mi?

Hayır. Yalnızca en yüksek tarih değerini getirir. Sipariş kimliği, tutar ve diğer alanlar için bu tarihin ilgili sipariş kaydıyla eşleştirilmesi gerekir.

IN ile EXISTS her zaman aynı sonucu mu üretir?

Hayır. Benzer üyelik kontrollerinde aynı görünen sonuçlar verebilirler; fakat NULL değerleri, korelasyon koşulları ve sorgunun ifade ettiği mantık farklı sonuçlara yol açabilir.

JOIN kullandıktan sonra müşteri satırları neden çoğalır?

Bir müşteri birden fazla siparişle eşleşiyorsa her eşleşme ayrı sonuç satırı üretir. Tek satır gerekiyorsa eşleşme koşulunu daraltmalı veya hangi kaydın seçileceğini açıkça tanımlamalısın.

Doğru çözüm, hatayı gizlemekten önce sorgunun tek değer mi, özet mi, varlık kontrolü mü yoksa tam kayıt mı üretmesi gerektiğini belirlemekle başlar.

Bu içerik aradığın cevabı verdi mi?
Yanıtın, hangi yazıları geliştirmemiz gerektiğini anlamamıza yardımcı olur.
Bu içeriğin üretilmesinde yapay zeka araçlarından destek alınmıştır.

Bu konudan sonra ne okuyabilirsin?

Tüm yazılar

İlgili Eğitimler

Berk Keskin, yazılım geliştirici ve eğitmen
Yazar

Berk Keskin Kimdir?

Yazılıma 12 yaşında başladı; İzmir Ekonomi Üniversitesi'ni bölüm birincisi ve yüksek şeref öğrencisi olarak tamamladı. Bugün yalnızca eğitim vermekle kalmıyor, sektörde aktif olarak yazılım projeleri geliştiriyor ve gerçek dünya deneyimini birebir derslerine taşıyor. Ezberden uzak, mühendislik zihniyetini merkeze alan sürdürülebilir öğrenme sistemleri tasarlayarak sorgulayan, üreten ve problem çözebilen yeni nesil yazılımcılar yetiştiriyor.

Sektörel Deneyim & Projeler

  • Ticarify Entegrasyon Yazılım logosu CEO Ticarify Entegrasyon YazılımPazaryerleri ve e-ticaret sitelerine otomatik e-fatura kesimi, sipariş ve kargo takibi hizmetleri sunan e-Dönüşüm platformunun API mimarisini ve yazılım ekibini yönetmektedir.
  • Benim Düğünüm logosu CEO Benim DüğünümDijital etkinlik ve anı paylaşım platformu.
  • Siberdizayn logosu Yazılım Ekibi Lideri SiberdizaynYüksek anlık oyuncu trafiğine sahip oyun kontrol panelleri ve sunucu altyapıları geliştiren yazılım ekibine liderlik etmektedir.
  • MEDYOGRAFYA 360° Dijital Çözümler logosu Dijital Strateji Lideri MEDYOGRAFYA 360° Dijital ÇözümlerŞirketlerin dijital çözümlerde uzun vadede nasıl ilerlemesi gerektiği ve dijital dönüşüm süreçlerinin yönetilmesine destek olmaktadır.
  • İzmir Ekonomi Üniversitesi logosu Danışma Kurulu Üyesi İzmir Ekonomi ÜniversitesiMezun olduğu üniversitesinde, Bilgisayar Programcılığı bölümünün akademik müfredatını güncel sektör ihtiyaçlarına göre şekillendirmek adına Danışma Kurulu'nda görev almaktadır.
WhatsApp Hemen Ara