İçeriğe geç
Educora
Orta16 dk7 / 22

GROUP BY ve HAVING: gruplara göre özetler

Satırları gruplara ayır, her grup için toplama fonksiyonlarını hesapla ve grupları HAVING ile filtrele.

Kendini test et
Bu derste öğreneceklerin
  • GROUP BY ile her grup için özet hesaplamak
  • WHERE ile HAVING arasındaki farkı açıklamak
  • Sorgu bölümlerinin mantıksal çalışma sırasını bilmek

Müdür soruyor: “Her şehirden kaç öğrencimiz var?” Geçen dersten tek bir şehri COUNT(*) ve WHERE city = 'Bakı' ile saymayı biliyoruz. Ama yedi şehir için yedi sorgu mu yazacağız? Hayır; GROUP BY tüm şehirlerin cevabını tek bir sorguyla verir.

GROUP BY: satırları gruplara ayırmak

GROUP BY sütun, aynı değere sahip satırları bir grupta toplar; toplama fonksiyonu her grup için ayrı hesaplanır. Sonuçta her grup için bir satır olur.

SQL
SELECT city, COUNT(*) AS students
FROM students
GROUP BY city
ORDER BY students DESC, city;
▸ Beklenen çıktı
city | students
Bakı | 4
Gəncə | 2
Sumqayıt | 2
Lənkəran | 1
Naxçıvan | 1
Quba | 1
Şəki | 1
  1. FROM students tablonun 12 satırını alır.
  2. GROUP BY city, şehri aynı olan satırları bir “sepete” koyar; 7 sepet oluşur.
  3. COUNT(*) her sepetteki satırları sayar.
  4. Her sepet tek bir satıra dönüşür: şehir ve sayı.

Bir grup için birkaç toplama fonksiyonu da hesaplanabilir. Aşağıda her kategori için ürün sayısı, ortalama fiyat ve toplam stok var.

SQL
SELECT category,
       COUNT(*)             AS products,
       ROUND(AVG(price), 2) AS avg_price,
       SUM(stock)           AS total_stock
FROM products
GROUP BY category
ORDER BY category;
▸ Beklenen çıktı
category | products | avg_price | total_stock
Accessories | 2 | 33.5 | 180
Electronics | 4 | 695.12 | 63
Games | 1 | 42 | 18
Home | 1 | 34.99 | 25
Stationery | 2 | 5.55 | 800

Birkaç sütuna ve ifadeye göre gruplama

GROUP BY içinde birkaç sütun olduğunda grubu değerlerin birleşimi belirler. Örneğin müşterileri ülke ve şehir ikilisine göre sayalım.

SQL
SELECT country, city, COUNT(*) AS customers
FROM customers
GROUP BY country, city
ORDER BY country, city;
▸ Beklenen çıktı
country | city | customers
Azerbaijan | Bakı | 2
Azerbaijan | Gəncə | 1
Russia | Moscow | 1
Türkiye | Ankara | 1
Türkiye | İstanbul | 1
United Kingdom | London | 1

Bir ifadeye göre de gruplanabilir. SUBSTR(order_date, 1, 7) tarihin ilk 7 karakterini, yani yılı ve ayı (2025-04) keser; böylece siparişleri aylara göre sayarız. SQL Server'da bu fonksiyonun adı SUBSTRING olur.

SQL
SELECT SUBSTR(order_date, 1, 7) AS month,
       COUNT(*) AS orders
FROM orders
GROUP BY SUBSTR(order_date, 1, 7)
ORDER BY month;
▸ Beklenen çıktı
month | orders
2025-01 | 2
2025-02 | 2
2025-03 | 2
2025-04 | 2
2025-05 | 1
2025-06 | 2
2025-07 | 1

HAVING: grupları filtrelemek

Peki yalnızca en az iki öğrencisi olan şehirleri istiyorsak? WHERE COUNT(*) >= 2 yazılamaz: WHERE, gruplar oluşmadan önce tek tek satırlara bakar ve henüz hiçbir şey sayılmamıştır. Gruplar için koşullar HAVING bölümüne yazılır; o, gruplamadan sonra çalışır.

SQL
SELECT city, COUNT(*) AS students
FROM students
GROUP BY city
HAVING COUNT(*) >= 2
ORDER BY city;
▸ Beklenen çıktı
city | students
Bakı | 4
Gəncə | 2
Sumqayıt | 2
SQL
SELECT course_id, ROUND(AVG(score), 1) AS avg_score
FROM enrollments
GROUP BY course_id
HAVING AVG(score) >= 85
ORDER BY avg_score DESC;
▸ Beklenen çıktı
course_id | avg_score
6 | 92.7
5 | 90.5
1 | 87.3
Ortalama puanı 85 ve üzeri olan dersler.
ÖlçütWHEREHAVING
Neyi filtrelertek tek satırlarıgrupları
Ne zaman çalışırgruplamadan öncegruplamadan sonra
Toplama fonksiyonu yazılabilir mi?hayırevet

WHERE ve HAVING aynı sorguda birlikte çalışabilir. Aşağıda önce WHERE stokta olmayan ürünü (Monitor) atar, kalanlar kategorilere ayrılır, HAVING ise yalnızca birden fazla ürünü olan kategorileri bırakır.

SQL
SELECT category, COUNT(*) AS in_stock
FROM products
WHERE stock > 0
GROUP BY category
HAVING COUNT(*) > 1
ORDER BY category;
▸ Beklenen çıktı
category | in_stock
Accessories | 2
Electronics | 3
Stationery | 2

Sorgunun çalışma sırası

Sorguyu bir sırayla yazarız, VTYS ise onu mantıksal olarak başka bir sırayla çalıştırır. Bu sırayı bilmek birçok hatayı açıklar; örneğin toplama fonksiyonları ve takma adlar neden WHERE içinde çalışmaz da ORDER BY içinde çalışır.

  1. FROM — tablodan satırlar alınır
  2. WHERE — satırlar filtrelenir
  3. GROUP BY — satırlar gruplara ayrılır
  4. HAVING — gruplar filtrelenir
  5. SELECT — sütunlar ve takma adlar hesaplanır
  6. ORDER BY — sonuç sıralanır
  7. LIMIT — gereken sayıda satır alınır
Örnek görev

Hangi müşteriler tüm siparişlerinde toplam en az 5 adet ürün almıştır?

Çözümü göster
1) Siparişleri müşteriye göre gruplarız: GROUP BY customer_id.
2) Her gruptaki miktarları toplarız: SUM(quantity).
3) Grupları filtreleriz: HAVING SUM(quantity) >= 5.
Cevap: 2 numaralı müşteri (21 adet) ve 1 numaralı müşteri (13 adet).
SQL
SELECT customer_id, SUM(quantity) AS items
FROM orders
GROUP BY customer_id
HAVING SUM(quantity) >= 5
ORDER BY items DESC;
▸ Beklenen çıktı
customer_id | items
2 | 21
1 | 13
Müşterilerin adlarını da görmek için orders tablosunu customers ile birleştirmek gerekir; bunu bir sonraki derste öğreneceksin.
Alıştırma

courses tablosunda her branş (subject) için ders sayısını (courses) ve kredilerin toplamını (credits) göster. Sonucu branş adına göre sırala.

Alıştırma · SQL
SELECT subject
FROM courses
ORDER BY subject;
▸ Beklenen çıktı
subject | courses | credits
Chemistry | 1 | 3
English | 1 | 2
History | 1 | 2
Informatics | 1 | 3
Math | 2 | 7
Physics | 1 | 4
Alıştırma

Ortalama puanı 85'in üzerinde olan öğrencileri bul: student_id ve virgülden sonra 1 basamağa yuvarlanmış ortalama puan (avg_score). Ortalama puana göre azalan, eşitlikte student_id değerine göre artan sırada sırala.

Alıştırma · SQL
SELECT student_id, ROUND(AVG(score), 1) AS avg_score
FROM enrollments
-- group and filter the groups
▸ Beklenen çıktı
student_id | avg_score
11 | 95.5
3 | 92.5
10 | 91
1 | 90
5 | 89
6 | 88

Önemli noktalar

  • GROUP BY aynı değerlere sahip satırları gruplar; sonuçta her grup için bir satır olur.
  • SELECT içindeki her sütun ya GROUP BY içinde ya da bir toplama fonksiyonunun içinde olmalıdır.
  • WHERE satırları gruplamadan önce, HAVING ise grupları gruplamadan sonra filtreler.
  • Toplama fonksiyonlu koşullar (COUNT(*) >= 2) yalnızca HAVING içine yazılır.
  • Mantıksal sıra: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT.

Kendini test et

10 soru. Her doğru cevap XP kazandırır.

1 / 10
SELECT city, COUNT(*) FROM students GROUP BY city sorgusunda GROUP BY city ne yapar?