group etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
group etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

28 Haziran 2015 Pazar

Temel SQL Dersi 16: HAVING Elemanı



HAVING


HAVING ifadesi bu iki yazıda anlatılanların devamı, çünkü sadece GROUP BY ifadesi ile birlikte kullanılan bir ifade. Aslında HAVING ifadesinin işlevi WHERE ifadesininkine çok benziyor. Ancak kümeleme fonksiyonları ile WHERE ifadesi birlikte kullanılamadığından HAVING ifadesine ihtiyaç duyulmuştur. Meseleyi daha iyi izah edebilmek için hemen örneklere geçelim. Öncelikle bir önceki makalede de kullandığımız aşağıdaki kisiler tablosunu inceleyelim. Sonra bu tablo üzerinden örneklerle konuyu inceleyeceğiz.
idAdSoyadYasCinsiyetŞehirÜlkeMaaş
2AhmetYılmaz201AnkaraTürkiye2000
3MehmetEfe221BoluTürkiye2000
4AyşeCan230İstanbulTürkiye3500
5FatmaAk350AnkaraTürkiye3200
6JohnSmith451New YorkUSA3500
7EllenSmith400New YorkUSA3500
8HansMüller301BerlinAlmanya4000
9FrankCesanne351ParisFransa3700
10AbbasDemir261AdanaTürkiye2000
11HaticeTopçu260HatayTürkiye2200
12GülsümDemir350AdanaTürkiye2000

Öncelikle aşağıdaki 2 sorgu örneğini inceleyelim:
SELECT ülke, AVG(maaş) FROM `kisiler` GROUP BY ülke
Bu sorgu ülkelere göre maaş ortalamasını verir ve çıktısı aşağıdaki gibidir:
ülkeAVG(maaş)
Almanya4000.0000
Fransa3700.0000
Türkiye2414.2857
USA3500.0000

 SELECT ülke, AVG(maaş) FROM `kisiler` WHERE yas > 30 GROUP BY ülke
Dikkat ederseniz bu sorgunun bir öncekinden tek farkı “WHERE yas > 30″ kısmı. Sorgu yine ülkelere göre maaş ortalamasını hesaplıyor ama bu hesaba yalnızca yaşı 30’dan büyük olan çalışanları katıyor. Sorgunun çıktısı aşağıdaki gibidir:
ülkeAVG(maaş)
Fransa3700.0000
Türkiye2600.0000
USA3500.0000

Şimdi de yaş ortalaması 30’un üzerinde olan ülkelerin maaş ortalamalarını getiren sorguyu yazmaya çalışalım. Burada 30 yaş üstü koşulu çalışanlar için değil ülkeler için (yani gruplar) geçerli. O halde yine yukarıdaki sorgularda olduğu gibi ülkelere göre gruplama yapacağız ama bu sefer koşulu gruplar için yazacağız.
 SELECT ülke, AVG(maaş) FROM `kisiler` GROUP BY ülke HAVING AVG(yas) > 30
Sorgunun çıktısı aşağıdaki gibi olacaktır:
ülkeAVG(maaş)
Fransa3700.0000
USA3500.0000
Sorgunun döndürdüğü sonuç kümesine bakarak iki ülkenin (Türkiye ve Almanya) yaş ortalamalarının 30’dan küçük olduğunu söyleyebiliriz.
Şimdi de çalışan sayısı 1’den fazla olan şehirleri ve çalışan sayılarını getiren sorguyu yazalım.
 SELECT şehir, COUNT(*) FROM `kisiler` GROUP BY şehir HAVING COUNT(*) > 1
Sorgunun çıktısı aşağıdaki gibi olacaktır.
şehirCOUNT(*)
Adana2
Ankara2
New York2

Şimdi yazacağımız sorgunun açıklaması şöyle: Maaş ortalaması 3000’den fazla olan ülkelerdeki erkek çalışanların maaş ortalaması. Burada gruplamanın ülkelere göre yapılacağı ve yalnızca erkek çalışanların hesaba katılacağı açık.
 SELECT ülke, AVG(maaş) FROM `kisiler` WHERE Cinsiyet=1 GROUP BY ülke HAVING AVG(maaş) > 3000
Sorgunun çıktısı aşağıdaki gibidir. Bu sorguda WHERE ve HAVING ifadeleri birlikte kullandığımızdan farklarını rahatça görebiliyoruz.
ülkeAVG(maaş)
Almanya4000.0000
Fransa3700.0000
USA3500.0000
Yukarıdaki sorguyu biraz değiştirelim: Erkek çalışanların sayısı 1’den fazla olan ülkelerin maaş ortalamasını getiren sorgu:
 SELECT ülke, AVG(maaş) FROM `kisiler` WHERE Cinsiyet=1 GROUP BY ülke HAVING COUNT(*) > 1
Sorgunun çıktısı aşağıdaki gibi olacaktır:
ülkeAVG(maaş)
Türkiye2000.0000
Sorguları ve “ne yaptıklarını” dikkatle incelerseniz konuyu daha iyi anlayacaksınız. Bitirmeden önce WHERE ifadesinin her zaman GROUP BY ifadesinden önce geldiğini HAVING’in ise her zaman sonra geldiğini hatırlatalım.

Temel SQL Dersi 15: GROUP BY Elemanı



GROUP BY Elemanı

Adından da anlaşılacağı üzere GROUP BY ifadesi gruplama yapar. Yani sonuç kümesini bir veya birden fazla kolona göre gruplar. Öncelikle bir önceki makalede de kullandığımız aşağıdaki kisiler tablosunu inceleyelim. Sonra bu tablo üzerinde biraz gruplama yapacağız.

idAdSoyadYasCinsiyetŞehirÜlkeMaaş
2AhmetYılmaz201AnkaraTürkiye2000
3MehmetEfe221BoluTürkiye2000
4AyşeCan230İstanbulTürkiye3500
5FatmaAk350AnkaraTürkiye3200
6JohnSmith451New YorkUSA3500
7EllenSmith400New YorkUSA3500
8HansMüller301BerlinAlmanya4000
9FrankCesanne351ParisFransa3700
10AbbasDemir261AdanaTürkiye2000
11HaticeTopçu260HatayTürkiye2200
12GülsümDemir350AdanaTürkiye2000

Şimdi yukarıdaki tabloyu ülkelere göre gruplasaydık ne olurdu? Görüldüğü gibi 4 farklı ülke olduğuna göre 4 farklı grup oluşacaktı. Bu gruplar Türkiye’de çalışanlar, Amerika’da çalışanlar, Fransa’da çalışanlar ve Almanya’da çalışanlar olarak ifade edilebilir. Bu ifade biçimi oldukça anlaşılır zira saf Türkçe. Biraz daha teknik bir ifade kullanmak istersek; Ülke alanında Türkiye, Amerika, Fransa veya Almanya değerleri bulunan kayıtların gruplaşması diyebiliriz.
Hemen bu örneği sorgu olarak yazalım:
 SELECT ülke FROM `kisiler` GROUP BY ülke
Sorgunun çıktısı aşağıdaki gibi olacaktır:
ülke
Almanya
Fransa
Türkiye
USA


Burada SELECT ifadesinden sonra ülke kolonu dışında kolonlar yazarsak, bu kolonlar için gelecek olan değerler anlamlı olmayacaktır. Mesela:
SELECT * FROM `kisiler` GROUP BY ülke
idAdSoyadYasCinsiyetŞehirÜlkeMaaş
8HansMüller301BerlinAlmanya4000
9FrankCesanne351ParisFransa3700
2AhmetYılmaz201AnkaraTürkiye2000
6JohnSmith451New YorkUSA3500


Sonuç kümesine baktığımızda ülke alanı hariç diğer alanlar için gruba ait kayıtlardan ilkinin değerlerinin geldiğini görürüz. Bu da yukarıdaki tabloyu anlamsız kılıyor. Bütün bunları anlatmamın sebebi GROUP BY’ın kümeleme fonksiyonları ile nasıl anlamlı hale geldiğini göstermek.
Örneğin ülkelerin ortalama maaşını görmek istesek:
SELECT ülke, AVG(maaş) FROM `kisiler` GROUP BY ülke
Sorgunun çıktısı aşağıdaki gibi olacaktır:
ülkeAVG(maaş)
Almanya4000.0000
Fransa3700.0000
Türkiye2414.2857
USA3500.0000


Burada geri planda kayıtlar ülke değerlerine göre gruplandı ve her grubun maaş değerinin ortalaması hesaplanarak yukarıdaki sonuç kümesi elde edildi. Sonuç olarak GROUP BY kullanırken SELECT’ten sonra GROUP BY ile kullandığımız alanları ve kümeleme fonksiyonlarını kullanmamız gerekiyor.
Eğer her ülkeden kaç çalışanın olduğunu görmek istersek:
SELECT ülke, COUNT(*) AS sayı FROM `kisiler` GROUP BY ülke
Sorgunun çıktısı aşağıdaki gibi olacaktır:
ülkesayı
Almanya1
Fransa1
Türkiye7
USA2


Örneğin maaş ortalamasını bayanlar ve erkekler olarak görmek isteseydik:
SELECT cinsiyet, AVG(maaş) AS sayı FROM `kisiler` GROUP BY cinsiyet
Sorgunun çıktısı aşağıdaki gibi olacaktır:
cinsiyetsayı
02880.0000
12866.6667


GROUP BY ile birden fazla alan kullanımı
GROUP BY ifadesinden sonra birden fazla alan kullanabiliriz. Örneğin kayıtları önce ülkelere göre gruplayıp sonra her bir grubu kendi içinde şehirlere göre gruplamak istesek:
SELECT ülke, şehir FROM `kisiler` GROUP BY ülke, şehir
Sorgunun çıktısı aşağıdaki gibi olacaktır:
ülkeşehir
AlmanyaBerlin
FransaParis
TürkiyeAdana
TürkiyeAnkara
TürkiyeBolu
TürkiyeHatay
Türkiyeİstanbul
USANew York


Türkiye dışındaki gruplarda tek bir şehir varken, Türkiye grubunun da kendi içinde 5 gruba ayrıldığına dikkat edin. Her bir gruba ait kaç adet çalışan olduğunu görmek istersek sorguya ufak bir ekleme yapmamız yeterli olur:
SELECT ülke, şehir, COUNT(*) FROM `kisiler` GROUP BY ülke, şehir
Sorgunun çıktısı aşağıdaki gibi olacaktır:
ülkeşehirCOUNT(*)
AlmanyaBerlin1
FransaParis1
TürkiyeAdana2
TürkiyeAnkara2
TürkiyeBolu1
TürkiyeHatay1
Türkiyeİstanbul1
USANew York


Şimdi de her ülke için bayan ve erkek çalışanların sayısını ve yaş ortalamalarını bulalım:
SELECT ülke, cinsiyet, AVG(yas), COUNT(*) FROM `kisiler` GROUP BY ülke, cinsiyet
Sorgunun çıktısı aşağıdaki gibi olacaktır:
ülkecinsiyetAVG(yas)COUNT(*)
Almanya130.00001
Fransa135.00001
Türkiye029.75004
Türkiye122.66673
USA040.00001
USA145.00001


Yukarıdaki tablodan mesela, Türkiye’den 4 bayan, 3 erkek çalışanın olduğunun ve bayanların yaş ortalamalarının 29.7 erkeklerinkinin ise 22.6 olduğunu okuyabiliriz.
GROUP BY İfadesini  WHERE ifadesi ile birlikte kullanmak
Öncelikle WHERE ifadesinin sorguda her zaman group by’dan önce geldiğini belirtelim. Örneğin yukarıdaki sorguya maaşı 2000’den büyük olanlar gibi bir koşul ekleyelim.
SELECT ülke, cinsiyet, AVG(yas), COUNT(*) FROM `kisiler` WHERE maaş > 2000 GROUP BY ülke, cinsiyet
Sorgunun çıktısı aşağıdaki gibi olacaktır:
ülkecinsiyetAVG(yas)COUNT(*)
Almanya130.00001
Fransa135.00001
Türkiye028.00003
USA040.00001
USA145.00001


Bu sorgu biraz karışık görünse de aslında oldukça basit. Geri planda önce maaşı 2000’den küçük olan kayıtlar elendi. Yani önce sorgunun WHERE kısmı çalıştırıldı. Sonra kalan kayıtlar üzerinde sorgunun geri kalanı çalıştırıldı. Yani asında bir önceki sorgu tüm tablo yerine tablonun alt kümesi (maaşı 2000’den büyük olanlar) üzerinde çalıştırılmış oldu.