SQL COUNT farkı en net biçimde NULL değerler üzerinden anlaşılır: COUNT(*) satırların tamamını sayarken, COUNT(sütun) yalnızca ilgili sütunda NULL olmayan değerleri sayar. COUNT(1) satır sayma amacıyla kullanılır; COUNT(DISTINCT sütun) ise tekrar eden değerleri tekilleştirerek sayar ve NULL değeri sonuçta değer olarak saymaz.
Aşağıdaki tek örnek veri kümesi üzerinden ilerleyerek hangi durumda hangi COUNT kullanımının doğru olduğunu adım adım göreceğiz.
Örnek tabloları ve sayım sorusunu tanıyalım
Bir müşterinin kimliğini, adını ve e-posta adresini customers tablosunda tuttuğumuzu düşünelim. Siparişler ise orders tablosunda yer alsın. Her sipariş, customer_id alanı aracılığıyla bir müşteriye bağlansın.
customers tablosu
| customer_id | name | |
|---|---|---|
| 1 | Ayşe | [email protected] |
| 2 | Mehmet | [email protected] |
| 3 | Zeynep | NULL |
| 4 | Can | [email protected] |
| 5 | Elif | [email protected] |
Bu tabloda toplam beş müşteri satırı vardır. Zeynep’in e-posta değeri NULL’dır. Mehmet ve Can aynı e-posta adresini paylaşır. Bu tekrar, COUNT(DISTINCT email) sonucunu anlamak için önemlidir.
orders tablosu
| order_id | customer_id | category |
|---|---|---|
| 101 | 1 | Kitap |
| 102 | 1 | Elektronik |
| 103 | 2 | Kitap |
| 104 | 4 | Ev |
Elif’in bu veri kümesinde siparişi yoktur. Bu ayrıntı, ileride GROUP BY ve LEFT JOIN kullanırken bir müşterinin neden sıfır siparişle sonuçlarda görünebileceğini açıklamamıza yardımcı olacaktır.
Şimdi temel soruyu kuralım: COUNT(*) satırları mı, yoksa bir sütundaki değerleri mi sayar? Doğru cevabı bulmak için yıldız, sütun, sabit ifade ve tekilleştirme arasındaki farkı karşılaştırmamız gerekir.
COUNT(*), COUNT(sütun), COUNT(1) ve COUNT(DISTINCT sütun) nasıl çalışır?

Önce sorguları aynı customers tablosu üzerinde çalıştıralım.
SELECT COUNT(*) AS toplam_satir
FROM customers;
Beklenen sonuç: 5. COUNT(*), belirli bir sütunun dolu olup olmadığına bakmadan sonuç kümesindeki satırları sayar. Bu nedenle NULL e-posta adresi bulunan Zeynep’in satırı da sayıya dâhildir.
SELECT COUNT(email) AS email_sayisi
FROM customers;
Beklenen sonuç: 4. COUNT(email), email sütunundaki NULL olmayan değerleri sayar. Beş satırdan yalnızca birinde NULL bulunduğu için sonuç dörttür.
SELECT COUNT(1) AS satir_sayisi
FROM customers;
Beklenen sonuç: 5. Buradaki 1, her satır için değerlendirilen sabit bir ifadedir. COUNT(1) satır sayma amacıyla kullanılır. Bunu, NULL içeren bir sütunu sayan COUNT(email) ile karıştırmamak gerekir. Bu ifade için performans üstünlüğü varsaymak yerine, sorgunun neyi saydığını doğru okumaya odaklanmalısın.
SELECT COUNT(DISTINCT email) AS tekil_email_sayisi
FROM customers;
Beklenen sonuç: 3. NULL olmayan e-posta değerleri şunlardır: [email protected], [email protected] ve [email protected]. Mehmet ile Can’ın aynı e-posta adresi tek değer olarak kabul edilir. Genel SQL kullanımında COUNT(DISTINCT sütun), NULL değerleri sayılabilir bir değer olarak hesaba katmaz; bu davranış PostgreSQL ve MySQL belgelerinde de bu şekilde açıklanır.
| Sorgu | Beklenen sonuç | Neden? |
|---|---|---|
COUNT(*) |
5 | Tüm satırları sayar. |
COUNT(email) |
4 | NULL olmayan e-posta değerlerini sayar. |
COUNT(1) |
5 | Her satırdaki sabit ifadeyi değerlendirerek satırları sayar. |
COUNT(DISTINCT email) |
3 | Tekrarlanan e-postaları birleştirir, NULL değeri saymaz. |
NULL neden COUNT(sütun) sonucunu değiştirir?
NULL, boş metin veya sıfır değildir. Bir değerin bilinmediğini ya da o kayıt için mevcut olmadığını ifade eder. Bu nedenle NULL bulunan bir hücre, normal bir metin veya sayı gibi sayılabilir bir değer kabul edilmez.
Örneğimizde beş müşteri satırı vardır:
- Ayşe’nin e-postası dolu.
- Mehmet’in e-postası dolu.
- Zeynep’in e-postası NULL.
- Can’ın e-postası dolu.
- Elif’in e-postası dolu.
Satırları sayarsak sonuç 5 olur. Bu, COUNT(*) sonucudur. E-posta değerlerini sayarsak Zeynep’in NULL hücresi dışarıda kalır ve sonuç 4 olur. Bu da COUNT(email) sonucudur. Elle hesaplama şu şekilde özetlenebilir: 5 toplam müşteri - 1 NULL email = 4 dolu email.
Hangi COUNT ifadesini seçeceğine karar verirken şu üç soruyu sor:
- Satırların tamamını mı sayıyorum?
COUNT(*)kullan. - Belirli bir sütunda değeri bulunan kayıtları mı sayıyorum?
COUNT(sütun)kullan. - Tekil değerleri mi sayıyorum?
COUNT(DISTINCT sütun)kullan.
Bu ayrım, özellikle NULL içeren müşteri bilgileri, eksik iletişim alanları ve tekrar eden e-posta adresleriyle çalışırken beklenmedik sonuçları önler.
GROUP BY ile müşteri veya kategori bazında doğru sayım
GROUP BY, toplam satır sayısını tek bir sonuç olarak vermek yerine, belirlediğin grupların her biri için ayrı hesaplama yapar. Bu nedenle sorgudan önce şu soruyu sormalısın: Hangi satırları sayıyorum ve hangi sütuna göre grupluyorum?
Örneğimizde orders tablosunda şu kayıtların bulunduğunu düşünelim:
| order_id | customer_id | category |
|---|---|---|
| 101 | 1 | Kitap |
| 102 | 1 | Elektronik |
| 103 | 2 | Kitap |
| 104 | 2 | Kitap |
| 105 | 3 | NULL |
Müşteri bazında sipariş satırlarını saymak
SELECT
customer_id,
COUNT(*) AS siparis_satiri_sayisi,
COUNT(order_id) AS null_olmayan_siparis_id_sayisi
FROM orders
GROUP BY customer_id;
Beklenen sonuç şöyledir:
| müşteri | sipariş satırı sayısı | NULL olmayan sipariş kimliği sayısı |
|---|---|---|
| 1 | 2 | 2 |
| 2 | 2 | 2 |
| 3 | 1 | 1 |
Burada önce customer_id değerleri gruplara ayrılır. Ardından COUNT(*) her grubun bütün satırlarını, COUNT(order_id) ise yalnızca order_id değeri NULL olmayan satırları sayar. Sipariş kimlikleri NULL içermediği için iki sonuç aynı görünür.
Kategori bazında sayım yapmak
SELECT
category,
COUNT(*) AS satir_sayisi,
COUNT(category) AS kategori_degeri_sayisi
FROM orders
GROUP BY category;
Beklenen sonuç:
| kategori | satır sayısı | NULL olmayan kategori sayısı |
|---|---|---|
| Elektronik | 1 | 1 |
| Kitap | 3 | 3 |
| NULL | 1 | 0 |
category değeri NULL olan satır da bir sipariş satırıdır; bu yüzden COUNT(*) sonucuna dâhil edilir. Ancak COUNT(category), NULL değeri saymaz. Böylece aynı grup içinde “kaç satır var?” ile “kaç NULL olmayan kategori değeri var?” sorularının farklı sonuçlar üretebildiğini görürsün.
WHERE koşulu gruplamadan önce çalışır
SELECT
customer_id,
COUNT(*) AS kitap_siparisi
FROM orders
WHERE category = 'Kitap'
GROUP BY customer_id;
Bu sorguda önce Elektronik ve NULL kategorili satırlar elenir, sonra kalan Kitap kayıtları müşteri bazında gruplanır. Sonuçta 1 numaralı müşteri için 1, 2 numaralı müşteri için 2 satır bulunur; 3 numaralı müşteri sonuçta yer almaz. Çünkü GROUP BY yalnızca WHERE koşulundan geçen satırları gruplar.
COUNT(1) de her grup içindeki satırları sayar; sabit 1 değeri NULL olmadığı için bu kullanım COUNT(*) ile aynı satır mantığına sahiptir. Buna karşılık COUNT(DISTINCT customer_id), tekrar eden müşteri kimliklerini tekilleştirerek farklı müşteri sayısını bulmak için kullanılır. İhtiyacın satır sayısı mı, NULL olmayan değer sayısı mı, yoksa tekil değer sayısı mı olduğunu sorgudan önce netleştir.
LEFT JOIN ile hiç siparişi olmayan müşterileri nasıl sayarsın?

customers tablosunu ana tablo kabul edip orders tablosuyla LEFT JOIN yaptığında, tüm müşteriler sonuçta korunur. Siparişi olmayan müşteri için orders tablosundan gelen sütunler NULL görünür.
SELECT
c.customer_id,
c.name,
COUNT(*) AS count_yildiz,
COUNT(o.order_id) AS siparis_sayisi
FROM customers AS c
LEFT JOIN orders AS o
ON o.customer_id = c.customer_id
GROUP BY c.customer_id, c.name;
Örneğin müşterilerden 1 numaralının iki, 2 numaralının iki, 3 numaralının bir siparişi; 4 numaralının ise hiç siparişi olmasın. Beklenen çıktı şöyledir:
| müşteri | COUNT(*) | COUNT(o.order_id) |
|---|---|---|
| Ada | 2 | 2 |
| Bora | 2 | 2 |
| Ceren | 1 | 1 |
| Deniz | 1 | 0 |
Deniz için eşleşen sipariş bulunmasa da LEFT JOIN, ana tablodaki müşteriyi koruyan bir sonuç satırı oluşturur. Bu nedenle COUNT(*) değeri 1 olur. Fakat o.order_id NULL olduğu için COUNT(o.order_id) bu değeri saymaz ve gerçek sipariş sayısını 0 olarak verir.
JOIN sonrası sayım yaparken üç adımlı teşhis kullanabilirsin:
- Ana tabloyu belirle: Tüm müşteriler mi, yoksa yalnızca siparişi olan müşteriler mi sonuçta kalmalı?
- Eşleşmeyen satırı incele: Siparişi olmayan müşteride
orderssütunlarının NULL olup olmadığına bak. - Sayım ifadesini seç: Müşteri satırını mı, yoksa NULL olmayan sipariş kimliklerini mi saydığını belirle.
Yanlış COUNT sorgusunu düzeltme adımları ve kontrol listesi
“COUNT(*) NULL olmayan sütunları mı sayar?”
Hayır. COUNT(*) satırları sayar ve satırdaki diğer sütunların NULL olup olmamasından etkilenmez. Belirli bir sütunun NULL olmayan değerlerini saymak istiyorsan COUNT(sütun) kullanmalısın.
“LEFT JOIN içinde COUNT(*) neden sipariş sayısını yanlış verebilir?”
Çünkü siparişi olmayan müşteri için de JOIN sonucu bir satır oluşur. Gerçek sipariş kimliklerini saymak için COUNT(o.order_id) gibi NULL olabilecek değeri dikkate alan bir ifade seçilmelidir.
“COUNT(1), COUNT(sütun) gibi mi yorumlanır?”
Hayır. COUNT(1), her satır için NULL olmayan sabit bir değer bulunduğundan satırları sayar. Bir sütundaki NULL değerleri dışarıda bırakma davranışı bekleniyorsa ilgili sütun açıkça yazılmalıdır.
“Ne zaman DISTINCT gerekir?”
Aynı değer birden fazla satırda bulunabiliyor ve yalnızca farklı değerleri saymak istiyorsan COUNT(DISTINCT sütun) kullanılır. Normal COUNT(sütun) tekrarları da sayar.
Yanlış bir COUNT sorgusunu düzeltirken hedef metriği önce cümleyle yaz: “Toplam satırları mı, NULL olmayan değerleri mi, tekil değerleri mi sayıyorum?” Ardından JOIN sonrası oluşan satırları incele, NULL içerebilecek sayım ifadesini belirle ve küçük bir veri kümesinde sonucu elle kontrol et.
- Toplam satır mı sayılıyor?
- NULL olmayan değerler mi sayılıyor?
- Tekil değer sayısı mı gerekiyor?
- GROUP BY anahtarı doğru mu?
- LEFT JOIN sonrasında sayılan sütun uygun mu?
SQL dışındaki teknik konularda da kavramlarını pekiştirmek istersen Berk Akademi blogundaki yazılım içeriklerine göz atabilirsin.
SQL dışındaki yazılım bilgini nasıl kontrol edersin?
Bu yazıdaki örnekler SQL’de satır ve sütun saymayı anlamaya yöneliktir; dolayısıyla burada yapılan değerlendirme bir SQL sınavı değildir. Yazılım temellerini daha geniş bir çerçevede görmek istiyorsan değişkenler, koşullar, döngüler, nesne yönelimli programlama ve algoritmik düşünme gibi başlıklardaki seviyeni ayrıca kontrol edebilirsin.
İlgine ve hedeflerine uygun alanı seçerek ücretsiz yazılım bilgi testleri üzerinden Python, Java, C# veya algoritmik düşünme testlerinden birini çözebilirsin. Böylece SQL’deki sorgu mantığınla genel yazılım bilgini birbirine karıştırmadan, hangi konuda daha fazla pratik yapman gerektiğini daha net görebilirsin.
Sık Sorulan Sorular
COUNT(*) ile COUNT(email) arasındaki temel fark nedir?
COUNT(*), sorgu sonucuna gelen tüm satırları sayar. COUNT(email) ise yalnızca email sütununda NULL olmayan değerleri sayar. Bu nedenle aynı tabloda, bazı müşterilerin e-posta adresi eksikse iki sonuç farklı olabilir.
COUNT(email) NULL değerleri neden saymaz?
COUNT(sütun), yalnızca belirtilen sütunda değer bulunan satırları hesaba katar. NULL, boş bir metin veya sıfır değil, değer bulunmadığını ifade eden özel bir durumdur. Bu yüzden COUNT(email), e-posta alanı NULL olan satırları dışarıda bırakır.
COUNT(1) ile COUNT(*) aynı sonucu verir mi?
Standart satır sayma kullanımında COUNT(1) ve COUNT(*) aynı satır kümesi üzerinde aynı sonucu verir. Ancak sorguda WHERE, GROUP BY veya JOIN varsa sonucu belirleyen asıl unsur, bu işlemlerden sonra oluşan satır kümesidir.
LEFT JOIN kullandığımda hiç siparişi olmayan müşterileri neden COUNT(*) ile 1 görüyorum?
LEFT JOIN, siparişi olmayan müşteriyi de sonuçta tutar ve sipariş tarafındaki sütunları NULL bırakır. Müşteri satırı hâlâ bulunduğu için COUNT(*) bu grubu 1 olarak sayabilir. Yalnızca gerçek siparişleri saymak için sipariş tablosundaki bir sütunu, örneğin COUNT(siparis.id) ifadesini kullanmak gerekir.
GROUP BY ile sayım yaparken COUNT(*) mi yoksa COUNT(sütun) mu kullanmalıyım?
Amacın her gruptaki tüm sonuç satırlarını saymaksa COUNT(*) uygundur. Belirli bir sütunda değeri bulunan kayıtları saymak istiyorsan COUNT(sütun) kullanmalısın. Özellikle LEFT JOIN sonrasında, eşleşen kayıtları saymak için ilgili tablonun kimlik sütununu seçmek daha doğru sonuç verir.
Doğru sayım için önce hangi satırları saydığını, ardından NULL değerlerin hesaba katılıp katılmayacağını ve JOIN sonucunda oluşan satırları kontrol et.