- Konu sahibi
- #1
WHERE, sorguya alınacak satırları gruplama ve toplama işleminden önce filtreler. HAVING ise GROUP BY ile oluşturulan grupları, toplama sonucu hesaplandıktan sonra filtreler. Bu nedenle tek tek satırdaki koşullar için WHERE, COUNT, SUM veya AVG gibi toplama sonuçlarına göre koşul yazmak için HAVING kullanılır.Örneğin sipariş tablosunda yalnızca durumu
'tamamlandı' olan siparişleri dikkate alıp, toplam sipariş sayısı 10’dan fazla olan müşterileri bulmak istiyorsanız:
Kod:
SELECT musteri_id, COUNT(*) AS siparis_sayisi
FROM siparisler
WHERE durum = 'tamamlandı'
GROUP BY musteri_id
HAVING COUNT(*) > 10;
Burada
WHERE önce tamamlanmamış siparişleri eler. Ardından kalan satırlar müşteri bazında gruplanır. Son olarak HAVING, sipariş sayısı 10’dan fazla olan müşteri gruplarını bırakır. Sonuç, koşulu sağlayan müşterilerin kimliği ve tamamlanmış sipariş sayısıdır.Sorgu hangi sırayla çalışır?
Buradaki sıra mantıksal anlamı açıklar; optimizer fiziksel yürütmeyi başka sıraya çevirebilir. SQL sorgusunun yazılış sırası ile mantıksal değerlendirme sırası aynı değildir. Bu ayrım, hangi koşulun nereye yazılacağını anlamayı kolaylaştırır:
-
FROMve gerekiyorsaJOINile kaynak satırlar belirlenir. -
WHEREile tek tek satırlar filtrelenir. -
GROUP BYile kalan satırlar gruplara ayrılır. -
COUNT,SUMveyaAVGgibi toplama işlemleri hesaplanır. -
HAVINGile oluşan gruplar filtrelenir. -
SELECTsonucu şekillendirir;ORDER BYveLIMITvarsa sonuç sıralanır veya sınırlandırılır.
Bu yüzden aynı sorgu düzeyinde doğrudan WHERE COUNT(*) >10 yazılamaz; ayrı bir alt sorgunun aggregate sonucu kullanımı farklıdır.
WHERE çalıştığında henüz müşteri grupları ve bu grupların sayıları oluşmamıştır. Aynı koşul HAVING COUNT(*) > 10 şeklinde yazılmalıdır.Karar vermeyi kolaylaştıran kısa karşılaştırma
| Özellik | WHERE | HAVING |
|---|---|---|
| Filtrelediği şey | Gruplama öncesi satırlar | Gruplar/tek aggregate grup |
| Mantıksal aşama | Gruplamadan önce | Gruplamadan sonra |
| Aynı sorgu düzeyinde aggregate | Doğrudan COUNT(*) koşulu kullanılamaz | COUNT/SUM/AVG sonucu sınanabilir |
| Örnek | durum='aktif' | COUNT(*) >10 |
İki filtre aynı sorguda gerektiğinde ikisini birlikte kullanın. Satır koşulunu mümkün olduğunca
WHERE içinde yazmak, gruplamaya girecek veri miktarını azaltır ve sorgunun amacını daha açık hale getirir. Grup sonucu için gereken koşulu ise HAVING bölümünde bırakın.Somut örnek: şehir bazında toplam satış
Kod:
SELECT sehir, SUM(tutar) AS toplam_satis
FROM siparisler
WHERE iptal_edildi = 0
GROUP BY sehir
HAVING SUM(tutar) >= 10000
ORDER BY toplam_satis DESC;
Bu sorgunun anlamı şudur: İptal edilmemiş siparişleri al, şehir bazında grupla, her şehrin satış toplamını hesapla ve toplamı 10.000 veya daha fazla olan şehirleri göster.
iptal_edildi = 0 satır koşuludur; SUM(tutar) >= 10000 ise grup sonucu koşuludur.Eğer amaç yalnızca tutarı 100’den büyük siparişleri almaksa koşul
WHERE tutar > 100 olmalıdır. Bu koşulu HAVING içine taşımak çoğu durumda aynı anlama gelmez; çünkü HAVING tek tek siparişleri değil, grupların hesaplanmış sonucunu değerlendirir.Sık yapılan hatalar
Satır koşulunu HAVING içine taşımak
HAVING durum = 'tamamlandı' bazı SQL sistemlerinde çalışsa bile niyeti belirsizleştirebilir ve gruplama mantığını gereksiz yere karmaşıklaştırabilir. Gruplamadan önce uygulanabilecek koşulları WHERE bölümünde tutun.SELECT takma adını HAVING içinde kullanmak
Birçok veritabanında
SELECT içinde verilen toplam_satis gibi takma adlar HAVING içinde kullanılamaz veya farklı davranabilir. Taşınabilir bir sorgu için toplama ifadesini açıkça yazın: HAVING SUM(tutar) >= 10000. Veritabanınızın sözdizimi farklılıklarını ayrıca kontrol edin.NULL değerlerini gözden kaçırmak
COUNT(*) satırları sayar; COUNT(kolon) ise ilgili kolonu NULL olmayan satırları sayar. Bu iki ifade aynı sonucu vermeyebilir. Hangi varlıkları saymak istediğinizi netleştirin ve gerekirse WHERE kolon IS NOT NULL koşulunu kullanın.Kaynaklar
Sık sorulan sorular
GROUP BY kullanmadan HAVING kullanılabilir mi?
Evet, aggregate sorguda tüm seçilen satırlar tek grup sayılabilir. Örneğin
SELECT COUNT(*) FROM siparisler HAVING COUNT(*) > 10 tek toplamı sınar; bunun için yapay bir GROUP BY eklemek gerekmez. Gruplanmamış normal sütunları SELECT/HAVING’de kullanmanın kuralları ise veritabanına göre değişir.WHERE yerine her zaman HAVING kullanılabilir mi?
Hayır. İkisi bazı basit sorgularda benzer sonuç üretebilse de farklı aşamalarda çalışır. Satırları erken filtrelemek için
WHERE, gruplama sonucunu filtrelemek için HAVING kullanmalısınız.
Son düzenleme: