GROUP BYile her grup için özet hesaplamakWHEREileHAVINGarası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.
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
FROM studentstablonun 12 satırını alır.GROUP BY city, şehri aynı olan satırları bir “sepete” koyar; 7 sepet oluşur.COUNT(*)her sepetteki satırları sayar.- 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.
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.
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.
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.
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
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
| Ölçüt | WHERE | HAVING |
|---|---|---|
| Neyi filtreler | tek tek satırları | grupları |
| Ne zaman çalışır | gruplamadan önce | gruplamadan sonra |
| Toplama fonksiyonu yazılabilir mi? | hayır | evet |
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.
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.
FROM— tablodan satırlar alınırWHERE— satırlar filtrelenirGROUP BY— satırlar gruplara ayrılırHAVING— gruplar filtrelenirSELECT— sütunlar ve takma adlar hesaplanırORDER BY— sonuç sıralanırLIMIT— gereken sayıda satır alınır
Hangi müşteriler tüm siparişlerinde toplam en az 5 adet ürün almıştır?
Çözümü gösterÇözümü gizle
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).
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
orders tablosunu customers ile birleştirmek gerekir; bunu bir sonraki derste öğreneceksin.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.
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
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.
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 BYaynı değerlere sahip satırları gruplar; sonuçta her grup için bir satır olur.SELECTiçindeki her sütun yaGROUP BYiçinde ya da bir toplama fonksiyonunun içinde olmalıdır.WHEREsatırları gruplamadan önce,HAVINGise grupları gruplamadan sonra filtreler.- Toplama fonksiyonlu koşullar (
COUNT(*) >= 2) yalnızcaHAVINGiç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.
SELECT city, COUNT(*) FROM students GROUP BY city sorgusunda GROUP BY city ne yapar?