9 min read

SQL ile karmaşık sorgular yazma

Bu yazıda karmaşık sorgular yazmaya yarayan count, sum, avg, max, group by, exists gibi ifadeleri örneklerle uyguluyoruz.
SQL ile karmaşık sorgular yazma

Daha önceki yazılarda SQL SELECT, INSERT, UPDATE ve DELETE ifadeleri ile kayıtlarda okuma/yazma işlemleri yapmıştık.

SQL SELECT ile kayıt sorgulama
Bu yazıda yeni başlayanlar veya tekrar yapmak isteyenler için SQL ile çeşitli sorgulama örnekleri yazıyoruz.
SQL ile kayıt düzenleme : INSERT, UPDATE, DELETE
Bu yazıda veritabanına yeni kayıt ekleme, kayıt güncelleme ve kayıt silme işlemleri yapıyoruz.

Bu yazıda biraz daha işleri zorlaştırarak daha karmaşık problemleri çözeceğiz.

Not: bu yazıda yine MySQL veritabanı sunucusu ve örnek olarak Northwind veritabanı ile devam ediyoruz.

Getirilen kayıt sayısını sınırlama : LIMIT

Normalde bir SELECT sorgusunda uygun olan bütün kayıtlar getirilir. Fakat biz sadece ilk 10 kaydı istiyor olabiliriz. Veya seçim sonucu gelecek olan kayıt sayısının 50'yi aşmaması gerekiyor olabilir. Bu gibi sınırlamalar için MySQL de LIMIT kelimesi kullanılır.

Örnek olarak müşteri tablosundaki ilk 10 kaydı getirelim.

Şimdi de iş yeri sahibi kayıtlarından sadece 5 adedini isteyelim.

Tekil değerleri seçip çıkarma: DISTINCT

Bazı kayıtlarda tekrar eden değerler bulunur. Örneğin bir çok müşteri aynı şehirde ikamet ettiğinden city değeri bunlarda aynıdır.

Eğer ki bu şehirlerin bir listesini tekrar içermeden çıkarmak istiyorsak, DISTINCT ifadesi kullanırız.

Müşterilerin bulunduğu şehirlerin listesi

Daha önce öğrendiğimiz COUNT() ifadesi ile bu müşterilerin kaç adet farklı şehirde ikamet ettiğini de öğrenebiliriz.

16 farklı şehirde müşteri bulunuyor

Yine aynı yöntemle müşterilerin çalıştığı pozisyonların bir listesini çıkaralım.

Müşterilerin çalıştığı pozisyonların adları

Siparişlerin gönderildiği şehirlerin bir listesini çıkaralım.

Bütün siparişlerin gönderildiği şehirler

En az ve en çok olan değerleri bulma : MIN() ve MAX()

Şimdiye dek verilmiş olan en büyük siparişi bulmak için MAX() ifadesini kullanabiliriz.

En büyük sipariş ücretinin 300 olduğunu görüyoruz

Şimdi de sadece Las Vegas şehrinden verilmiş olan siparişlerin en düşük ücreti olanını bulalım.

Las Vegas şehrine yapılan siparişlerin en küçüğünün ücreti 5 dolar

Ortalama, Toplam hesaplama, Kayıt sayısı alma: AVG(), SUM() ve COUNT()

Şimdiye dek yapılan siparişlerin bir ortalamasını alalım.

Bütün siparişlerin ortalaması 44.54 dolar

Sadece New York şehrinden yapılan siparişlerin ortalamasını alalım.

Sadece Las Vegas şehrinde ve kredi kartıyla yapılan siparişlerin ortalamasını alalım.

Şimdiye kadar kredi kartıyla yapılan bütün siparişlerin sayısını alalım.

Şimdiye kadar yapılan bütün sipariş ücretlerinin toplamını bulalım.

Sadece kredi kartıyla yapılan siparişlerin toplamını bulalım.

Bir listede bulunan değerlerin bulunduğu kayıtları seçme: IN

Bir seçim yaparken bazen bir değil birden fazla değere göre koşul yazmak isteriz. Bu tür durumlarda IN kelimesi kullanabiliriz.

Örneğin elimizde bir şehir listesi var ve sadece bu şehirlere ait sipariş kayıtlarının toplamını hesaplamak istiyoruz. Bu listeyi bir IN kelimesinden sonra vererek problemi çözmüş oluruz.

Not: Bunun avantajı yazım kolaylığıdır. IN kullanmasaydık o zaman WHERE ship_city=A OR ship_city=B,.. şeklinde uzayan bir "veya" listesi yazmamız gerekirdi.

Bunu tersini olacak şekilde NOT IN şeklinde kullanırsak, bir listede olmayan değerlere sahip kayıtları bulabiliriz.

Örneğin siparişlerin gönderildiği şehirler arasında müşterilerimizin ikamet ettiği dışında bir yer var mı diye bakalım.

Benzer şekilde çek veya kredi kartı dışındaki ödeme şekilleriyle verilen siparişleri bulalım.

Çek ve kredi kartı dışında nakitle ödenmiş 4 sipariş bulunuyor

Metinlerde arama yapma: LIKE

Kayıtlarda bazen harf veya kelimeye göre arama yapmak isteriz. Örneğin kutu ile satılan ürünleri bulmak için LIKE ifadesini kullanabiliriz. Burada quantity sütununda "box" ifadesi bulunan kayıtlar aranıyor.

İki değer arasındaki kayıtları bulma: BETWEEN

Eğer bir değer aralığındaki kayıtları arıyorsak, örneğin fiyatı 50 ila 100 dolar arasındaki ürünler gibi, bunu BETWEEN ile ifade edebiliriz.

Fiyatı 50-100 dolar arasında olan 2 ürün bulunuyor

Bir tarih aralığındaki kayıtları da aynı yöntemler bulabiliriz. Örnek olarak 2006 yılının ocak ayındaki siparişleri getirelim.

2006 yılı Ocak ayında 4 adet sipariş verilmiş

Sütun veya tablo isimlerini kısaltma (Alias): AS

Zaman geçtikçe yazdığınız sql sorguları uzamaya, sütun ve tablo adları karışmaya başlar. Tekrar ederken hatalar yapmaya başlarsınız. İşte bazen bunları yeniden adlandırmak işimizi kolaylaştırabilir.

Örneğin 2006 yılı Ocak ayında yapılan siparişlerin tarih, ücret ve müşteri ismi alanlarını date, fee, name gibi kısa ve öz başlıklarla getirelim.

SELECT o.id, 
o.order_date AS date,  
o.shipping_fee AS fee, 
CONCAT(c.first_name, " ", c.last_name) AS name 
FROM northwind.orders o JOIN northwind.customers c 
WHERE o.customer_id = c.id 
AND order_date BETWEEN "2006-01-01" AND "2006-01-31"
AS kelimesi ile sütunlara basit adlar verebiliyoruz

Sonuçları sıralama: ORDER BY

Sorgulama sonucunda gelen satırları belirli bir sıraya koymak için ORDER BY kullanabiliriz. Bu sıralama alfabetik veya sayısal olabilir. Artan veya azalan bir şekilde sıralama yapmak için ASC ve DESC kelimeleri ilave edilir. Bunlardan herhangi biri yoksa default olarak ASC yani artan sıralama varsayılır.

Şimdi bir önceki sorguyu tekrarlayalım, yalnız bu defa sipariş ücreti büyükten küçüğe doğru sıralansın diyelim.

ORDER BY ve DESC ile sipariş ücretleri büyükten küçüğe doğru azalan bir şekilde sıralanıyor

Birden fazla sütunda da sıralama yapılabilir. Örneğin önce tarihe, sonra da sipariş ücretine göre sıralama yapabiliriz. Tarih artarken, sipariş ücreti azalabilir.  Hatta bunlara ilaveten isme göre de artacak şekilde sıralayabiliriz.

Bunu şöyle açalım: tarih sıralaması artacak; fakat aynı tarihe ait birden fazla kayıt varsa, bunlar da sipariş ücreti azalacak şekilde sıralanacak. Eğer bu iki değeri de aynı olan, yani aynı tarihte aynı ücrete sahip kayıtlar varsa, bunlar da isme göre alfabetik artan şekilde sıralanacak.

ORDER BY ile çoklu sıralamada tarih ve ücreti aynı olan kayıtlar alfabetik artarak sıralanıyor

Gruplayarak hesaplama: GROUP BY

Daha önce gördüğümüz count, min, max, avg, sum gibi işlemler sadece tek bir değer için değil, birden fazla değer için de yapılabilir. Şöyle ki; siparişlerin verildiği şehirlere göre gruplanması halinde her bir grubun ortalaması veya toplamı alınabilir. Böylece bir nevi özet çıkarmış oluruz.

Örneğin sipariş ücretlerinin şehir bazında toplamını alarak, azalan sıra ile listeleyelim. Bu sayede her şehrin sipariş tutarını özet olarak görebiliyoruz.

Siparişleri şehirlere göre gruplayarak toplamı alınıyor, azalarak sıralanıyor

Aynı şekilde her bir ödeme yöntemiyle verilen siparişlerin ortalamasını görelim. Böylece en çok hangisinin kazançlı olduğunu görebiliriz.

Siparişlerin seçili ödeme yöntemine göre ortalaması alınıyor

Siparişlerin günlük toplamını alalım, tarihi artan şekilde sıralayalım.

Her tarih için sipariş ücreti toplamı alınıyor

Her müşterinin verdiği sipariş sayısını almak içim siparişleri müşteri adına göre gruplayarak sayabiliriz. Bu sonuç müşterilerin sipariş alışkanlıkları hakkında bize fikir verecek.

Müşterilerin verdiği sipariş sayısı azalarak listeleniyor

Her şehirde verilen en büyük siparişi yine gruplama yöntemiyle getirelim.

Her şehir için verilen en büyük sipariş ücreti azalarak listeleniyor

Her eyalette bulunan müşterilerin sayısını alalım.

Eyaletlere göre müşteri sayıları azalarak listeleniyor

Her bir pozisyona sahip kaç adet müşteri olduğunu listeleyelim. Burada en çok müşterinin satın alma müdürü pozisyonunda olduğunu görebiliyoruz.

Pozisyon adları ile bunlara sahip olan müşterilerin sayıları azalarak listeleniyor

Birden fazla tablodan bilgi alarak da gruplama yapabiliriz.

Her şirketin verdiği sipariş sayısına bakalım. Siparişler orders tablosundan, şirketler de customers tablosundan alınıp join ile birleştirilecek. Bu birleşimden şirket adına göre gruplayarak kayıt sayısı alınacak.

Alfabetik listeye göre şirketler ve verdikleri sipariş adetleri

Bu tür count, sum, min, max ifadeleri where kelimesini kabul etmediğinden bunun yerine HAVING kelimesi ile bunlara koşul getirebiliyoruz.

Örneğin yukarıdaki listeden sadece 3'den fazla sipariş vermiş olanları seçelim.

En az 4 sipariş veren şirketlerin sipariş adetleri

Aradığım şartlara uyan kayıt var mı, yok mu testi: EXISTS

Aşağıdaki sorgu Miami şehrinden sipariş veren müşteriler varsa bunları isimlerini ve şirketlerini listeler.

Sipariş tablosuna baktığımızda bunun doğru olduğunu görüyoruz.

Burada exists kullanmadan where ve in kelimeleri ile de aynı sonucu alabiliriz.

Bu şekilde yine istediğimiz sonucu elde edebildik.

Burada exists'in avantajı şu: parantez içindeki alt-sorgu kısmı var/yok cevabı alındığı anda hemen sonlandığından, diğerine göre işlem daha performanslı olacaktır.

Son söz.

Bu yazıda SQL ile daha karmaşık sorgular yapmak için kullanılan şu ifadeleri örneklerle uyguladık: limit, distinct, count, avg, sum, min, max, in, like, between, as, order by, group by, having, exists. Bu yazı dizisinde değindiğimiz bütün ifadeleri bir kelime haznesi gibi kullanarak aklınıza gelebilecek en karmaşık sorgu cümlelerinin bile üstesinden gelebilirsiniz.

Bir sonraki yazıda zaman zaman kafa karışıklığına sebep olan JOIN ifadesini ve çeşitli kullanımlarını, artı ve eksileriyle inceleyeceğiz. Şimdilik görüşmek üzere, hoşçakalın.

SQL JOIN ile Kayıt Birleştirme
Bu yazıda sql sorgularında kayıt birleştirme amacıyla kullanılan JOIN ifadesinin çeşitli kullanım şekillerini inceliyoruz.