26-06-2007, 09:10 AM
1 - SQL NEDİR?
Veri tabanı ile bilgi alış verişi yapılmasını sağlayan bir dildir. Ancak SQL yalnız başına bir dil olarak algılanmamalıdır. Çünkü SQL, programlama dillerinin içine gömülen kodlar sayesinde çalışır. Kullanıldığı işletim sisteminin API (Application Programming Interface) fonksiyonlarını çalıştırır, ancak programcının bundan haberi olmaz.
Programlama dillerinin İngilizcesidir. Birkaç İngilizce kelimeden oluşur. Veri tabanı sorgusu yapan dile aslında T-SQL (Transact SQL) denir. SQL denince program değil, programlama dillerinde kullanılan sorgulama ara dili akla gelmelidir. Veri tabanlarını görüntülemeye ve yönetmeye yarayan programlara ise “Veri tabanı yönetim sistemi (Database Management System)” denir.
Piyasada pek çok veri tabanı yönetim sistemi vardır. Bunlardan en çok bilinenleri
• Microsoft SQL Server
• Oracle
• My-Sql
• Microsoft Access
• Informix
Çeşitli programlama dilleri gibi, SQL de standart hale getirilmiştir. ANSI tarafından standart hale getirilmiş ANSI SQL, her bir veri tabanı yönetim sistemi tarafından desteklenmesi gereken bir standarttır.
Veri Tabanı (Database)
Günümüzde veri tabanı (database), neredeyse her alanda kullanılmaktadır. Adres defterinizden bir adresi araştırmanız bile bir veri tabanı sorgusudur. Arama motorları sayesinde ulaştığınız bilgiler de yine veri tabanları ile haberleşir.
Bilgi: Veri tabanı, verileri derli toplu olarak saklamaya yarayan dosya ve dosyalar kümesidir.
Bilgi: Yaygın olarak veri tabanı yazılımlarına hatalı bir kullanışla “veritabanı” adı kullanılır. Ancak o programlar veri tabanı değil, veri tabanı yönetim sistemleridir (Database Management System). Veri tabanları bu yazılımlar sayesinde de kullanılabilir.
Tablolar (Tables)
Veri tabanında bilgilerin saklandığı alt birimlere tablo denir. Bir veri tabanında pek çok bilgi saklanabilir. Ancak bunların belirli bir şekilde ayrılması gerekir. Örneğin bir okulun tüm öğrencilerinin ve tüm notlarının tek bir tablo içerisinde tutulması karmaşaya yol açacaktır. Bu durumda veriler tablolara ayrılır. Ve tablolar birbirleriyle ilişkilendirilir.
Bir veri tabanında aynı isimde iki tablo bulunamaz. Tabi ki farklı veri tabanlarında aynı isimde tablolar bulunabilir.
Bilgi: Veri tabanına ait tabloların özelliklerini ve yerleşim şekillerini içeren bilgiye şema (schema) denir.
Kolonlar ve Veri Türleri (Columns and Datatypes)
Veri tabanının tablolardan oluştuğunu belirtmiştik. Tablolar da kolonlardan oluşur. Kolonlar, her birinde aynı türden veri saklayan birimlerdir. Örneğin öğrenci bilgilerini saklayan bir tabloda, bir kolon öğrenci numarasını, bir kolon adını ve diğer bir kolon da soyadını tutar. Yani her bir özelleşmiş bilgi, bir kolonda saklanır.
Verileri ayrı ayrı kolonlarda tutmak da çok önemlidir. Örneğin aynı isime sahip öğrencilere ulaşmak istendiğinde, eğer ad ve soyad bilgisi aynı kolonda tutulmuşsa işlem karmaşıklaşacaktır. Ancak ad ve soyad ayrı ayrı kolonlarda tutulmuşsa, işlem oldukça kolay olacaktır.
Her bir kolonun, saklayacağı bilginin özelliğini belirten veri türü bulunmaktadır. Bu veri türü sayesinde o kolonda saklanacak bilgi sınırlanır. Örneğin sayısal ifadelerin yer alacağı bir kolona karakter girilmesinin yasaklanması gibi.
Bilgi: Veri tabanlarınsa saklanacak bilgilerin türlerini belirten veri türleri, farklı veri tabanı yönetim sistemlerinde farklı isimlere sahip olabilirler. İşte bu farklılık, veri tabanı uyumu konusunda uyumsuzluk oluşturan en temel konudur. Aslında temel veri türleri aynı isimle kullanılsa da, özel veri türleri oldukça farklıdır.
Satırlar (Rows)
Bir tablodaki bilgiler satırlarda saklanır. Her bir kayıt kendi sırasında tutulur. Yine Excel tablolarını gözünüzde canlandırırsanız, dikey kolonlar tabloların kolonlarına, yatay satırlar ise tabloların satırlarına karşılık geldiğini görürsünüz.
Bilgi: Bir satır, bir kayıt (record) demektir.
Tekil Anahtarlar (Primary Keys)
Her bir tabloda, tablonun özelliğini taşıyan özel bir veya birden fazla kolon bulundurmalıdır. Örneğin öğrenci tablosunda, öğrenci numarasını tutan kolon bu tablodaki tekil bilgiyi tutar. O zaman tasarım sırasında öğrenci numarasını tutan kolon, tekil anahtar olarak belirtilmelidir.
Tekil anahtar kullanarak aynı kolonda farklı satırlarda aynı bilginin girilmesi engellenmiş olur. Ve bu kolona veri girilmemesi gibi bir durum söz konusu olamaz. (NULL değer kabul edilmez.) Tekil anahtar olarak belirlenen kolonların değiştirlmemesi gerekir.
2 - Veriye Ulaşmak
Bir tablodan bir veya birden fazla kolona ait bilgiye ulaşabilmek için SELECT ifadesi kullanılır.
2.1 - SELECT İfadesi
SQL’in birkaç İngilizce kelimeden oluştuğunu belirtmiştik. Aslında bu kelimelere anahtar sözcük denir. Tablolardan bilgi almak için SELECT anahtar sözcüğü kullanılır.
Bilgi: Anahtar sözcük, diğer programlama dillerinde olduğu gibi SQL’de de “reserverd keywords” yani değişken adı olarak kullanılması yasaklanmış sözcüklerdir. Örneğin SELECT adında bir tablo veya kolon kullanmamak gerekir.
Bir tablodan veri almak için iki bilgiye ihtiyaç vardır: Hangi tablodan ve hangi kolondan alınacağı.
SELECT ifadesinin sözdizimi (sentax):
SELECT <kolon ad(lar)ı> FROM <tablo adı>
Örnek 2.1: Ürünler tablosunda bulunan tüm ürünlerin adının listesini almak isteyelim.
Sorgu 1:
SELECT ProductName
FROM Products;
Ürünler tablosundan urun_adi olarak isimlendirilmiş kolondaki bilgilere ulaşmak için SELECT sorgusu kullanıldı.
Bilgi: Bir sorgudan elde edilen bilgiler topluluğuna “sonuç kümesi” denir.
Sonuç kümesinde görüntülenen veriler, veri tabanına girilişe göre listelenmiştir. Yani bir sıralama söz konusu değildir. İleride sıralanmış bilgiyi elde edebileceğiz.
SQL ifadeleri, aralarında istenildiği kadar boşluk kullanılarak çalıştırılabilir.
SQL’de büyük harf küçük harf duyarlılığı, veri tabanı yönetim sistemine göre değişir.
Bir tablodan birden fazla kolona ait bilgi almak için kolon adları arasına virgül konulur.
Örnek 2.2: Ürünler tablosunda bulunan ürünlerin kodunu, adını ve fiyatlarını listelemek isteyelim.
Sorgu 2 :
SELECT ProductID, ProductName, UnitPrice
FROM Products;
Ürünler tablosundan almak istediğimiz kolonarı birbirinden virgül ile ayırdık.
Bir tabloya ait tüm kolonların bilgisini almak için ise * operatörü kullanılır.
Örnek 2.3: Ürünler tablosundaki tüm bilgileri görüntülemek isteyelim.
Sorgu 3:
SELECT *
FROM Products
Sorguda * operatörü kullanınca, tablodaki tüm kolonlar görüntülenir. Sıralanması ise tabloda bulunduğu gibidir.
3 - Verilerin Sıralanması
SELECT sorgusu ile ORDER BY deyimini kullanarak sonuç kümesindeki verileri sıralamayı inceleyeceğiz.
3.1 - Sıralama İşlemi
Sonuç kümesindeki verileri istenilen kritere göre sıralamak için ORDER BY deyimini kullanacağız.
Bilgi: SQL ifadelerinde sorguları kuvvetlendirmek için çeşitli kalıplar kullanılır. Bu kalıplara deyim (clause) da denebilir.
ORDER BY Sözdizimi:
SELECT <kolon ad(lar)ı> FROM <tablo adı>
ORDER BY <kolon adı>
Örnek 3.1: Ürünler tablosundan alfabetik sıralı olarak ürün adlarını listeleyelim.
Sorgu 4:
SELECT ProductName
FROM Products
ORDER BY ProductName;
Bu sorgunun diğer sorgularımızdan farkı, ürün isimlerine göre sıralandırma yapabiliyor olmasıdır. Tablo ismi belirtildikten sonra hangi kolona göre sıralandırma yapılmak isteniyorsa ORDER BY deyiminden sonra o kolonun adı belirtilir. Burada dikkat edilmesi gereken, ORDER BY deyiminin en sonda kullanılıyor olmasıdır.
Görüntülenmek istenen kolonlara göre sıralama yaptırılacağına göre, SELECT listemizde yer almayan bir kolona göre sıralama yaptırmak pek kullanışlı olmayacaktır.
3.2 - Çoklu Kolonlara Göre Sıralama
Bazı durumlarda tek bir sıralama kriteri yeterli olmaz. Örneğin bir personel tablosunda soyada göre sıralanıp listenenen personelin bir de adına göre sıralanması istenebilir. Aynı soyada sahip işçiler için bu durum söz konusudur.
Çoklu kolona göre sıralama yapmak için, tıpkı çoklu kolon bilgilerini görüntülerken kolon isimleri arasına konulan virgüller gibi ORDER BY deyiminden sonra da kolonlar arasına virgül koymak gerekir.
Örnek 3.2: Ürünler tablosunda ürün kodu, fiyatı ve ismini, önce fiyata göre, sonra da ürün adına göre görüntülemek isteyelim.
Sorgu 5:
SELECT ProductName, UnitPrice
FROM Products
ORDER BY UnitPrice, ProductName;
Birden fazla kolona göre sıralama yapıldığı durumlarda, eğer ilk kritere göre sıralanan kayıtlarda aynı değere sahip kayıt varsa, ikinci kritere göre sıralama yapılır. Yani fiyatı 45 Ytl olan birden fazla ürün varsa, bu ürünler de kendi aralarında ürün adına göre sıralanacaktır.
3.3 - Kolon Pozisyonuna Göre Sıralama
ORDER BY deyiminden sonra kolon isimlerini sıralamak yerine, kolonun pozisyonuna göre de sıralama yapılabilir.
Örnek 3.3: Ürünler tablosunda ürün kodu, fiyatı ve ismini, önce fiyata göre, sonra da ürün adına göre görüntülemek isteyelim. Ancak sıralamada kolon adları yerine pozisyonları kullanalım.
Sorgu 6:
SELECT ProductID, ProductName, UnitPrice
FROM Products
ORDER BY 2, 3;
ORDER BY 2, SELECT listesinde belirtilen ikinci kolon adına göre sıralama yapılacağı anlamına gelir. ORDER BY 2, 3 ifadesinin eşdeğeri,
ORDER BY UnitPrice, ProductName
ifadesidir.
Kolon pozisyonu belirterek yeniden kodlamadan uzakaşmış olunur. Ancak pozisyona karşılık gelen isimlere dönüp bakmak da bazı durumlarda oldukça zaman kaybettirebilir.
3.4 - Sıralama Yönünün Belirtilmesi
Verilerin varsayılan sıralama yönü azdan çoğa artan (ascending) şekildedir. ORDER BY deyiminde hiçbir yön belirtilmezse bu artan olarak algılanır. Artan yönde sıralamak için ASC anahtar sözcüğü kullanılır. Azalan yönde (descending) sıralamak için ise DESC anahtar sözcüğü kullanılır.
Örnek 3.4: Ürünler tablosunu fiyata göre azalan sırada listeleyelim.
Sorgu 7:
SELECT ProductID, UnitPrice, ProductName
FROM Products
ORDER BY UnitPrice DESC;
Bu sorguda tabiki aynı değere sahip kayıtlar kendi aralarında sıralanma kriteri belirtilmeden rastgelen listelenmiştir.
Örnek 3.5: Ürünler tablosunu fiyata göre azalan sırada, sonra da ürün adına göre sıralı listeleyelim.
Sorgu 8:
SELECT ProductID, UnitPrice, ProductName
FROM Products
ORDER BY UnitPrice DESC, ProductName;
Bu sorguda aynı değere sahip kayıtlar kendi aralarında artan yönde sıralanmıştır.
4 - Veri Filtreleme - Arama
WHERE deyimi kullanılarak veriler arasında çeşitli kriterlere göre sorgu yapmayı öğreneceğiz.
4.1 - WHERE Deyiminin Kullanımı
Tablodaki veriler arasında belirli kritere uygun sorgu yapmak için WHERE deyimi kullanılır. Arama kriteri veya filteleme ifadesi olarak da isimlendirilebilir.
WHERE deyimi, FROM ifadesinin hemen sağında kullanılır.
WHERE Söz dizimi:
SELECT <kolon ad(lar)ı> FROM <tablo adı>
WHERE <kolon adı ve koşulu>
Örnek 4.1: Ürünler tablosudan ürün fiyatı 2.5 olanları listelemek isteyelim.
Sorgu 9:
SELECT ProductName, UnitPrice
FROM Products
WHERE UnitPrice = 2.5
Bu sorguda, ürünler tablosundan sadece ürün fiyatı 2.5 olan kayıtlar listelenecektir.
4.2 - WHERE Deyiminde Kullanılacak Operatörler
WHERE deyimi ile kombine edilebilecek çeşitli operatörler vardır. Bu operatörler tablo 4.1’de listelenmiştir.
Operatör Açıklama
= Eşitlik
<> Eşit değil
!= Eşit değil
< Küçüktür
> Büyüktür
<= Küçük eşittir
>= Büyük eşittir
!< Küçük değildir
!> Büyük değildir
BETWEEN İki değer arasında
IS NULL NULL Değer
Tablo 4.1: Where Deyimi Operatörleri
Bu operatörlerden bazıları birbirleriyle aynı anlama gelmektedir. Örneğin <> ile !=, !< ile >=, ve !> ile <= aynı etkileri oluşturur. Fakat bunların hepsi bazı veri tabanı yönetim sistemleri tarafından desteklenmez. Örneğin !=, !< ve !> operatörleri, Ms Access tarafından desteklenmez.
4.2.1 Tek Bir Değere Göre Arama
Önceki örnekte 2.5 liraya eşitliğe göre arama yaptık. Şimdi ise belirli bir fiyattan daha küçük fiyata sahip olanları listeleyelim.
Örnek 4.2: Ürünler tablosundan fiyatı 5 liradan küçük olanları listeleyelim.
Sorgu 10:
SELECT ProductName, UnitPrice
FROM Products
WHERE UnitPrice < 5
Örnek 4.3: Ürünler tablosundan fiyatı 15 liradan büyük ve eşit olanları listeleyelim.
Sorgu 11:
SELECT ProductName, UnitPrice
FROM Products
WHERE UnitPrice >= 15;
4.2.2 Eşitsizlik Durumları
Şimdi ise eşitsizlik durumlarını inceleyelim.
Örnek 4.4: Satıcı numarası 4 olan hariç tüm satıclardan alınan ürünleri listelemek isteyelim.
Sorgu 12:
SELECT SupplierID, ProductName
FROM Products
WHERE (SupplierID <> 4);
Örnek 4.5: Ürün adı Chang dışındaki tüm ürünleri listeleyelim.
Sorgu 13:
SELECT ProductName
FROM Products
WHERE ProductName <> 'Chang'
Örnekten de gördüğünüz gibi, metinsel ifadeler ile ilgili sorgu yaparken ayıraç olarak tekli tırnak kullanılır.
4.2.3 Belirli Bir Değer Aralığındaki Verilerin Araştırılması
Belirli bir değer aralığındaki verileri araştırmak için BETWEEN operatörü kullanılır. Bu operatörün kullanımı WHERE deyiminden biraz daha farklıdır. Arama yapılacak aralığın başlangıcı BETWEEN anahtar sözcüğünden sonra belirtilmeli ve AND anahtar sözcüğünden sonra ise aralığın bitiş noktası belirtilmelidir.
Örnek 4.6: Fiyatı 10 ve 20 lira arasında değişen ürünleri listeleyelim.
Sorgu 14:
SELECT ProductName , UnitPrice
FROM Products
WHERE UnitPrice BETWEEN 10 and 20
BETWEEN operatörü sayesinde istenilen her aralıkta bulunan verileri ulaşabilirsiniz. Önemli olan başlangıç ve bitiş aralığını belirtmektir. Örnekte fiyat araması için nümerik değerler kullanıldı. Ayrıca metin ifadeleri için de aralık belirtilebilir. Bu sefer metinin alfabetik duruma göre arama yapılacaktır.
Örnek 4.7: Ürün adı “Chang” ile “Longlife Tofu” arasında yer alan ürünleri listeleyelim.
Sorgu 15:
SELECT ProductName, UnitPrice
FROM Products
WHERE ProductName BETWEEN 'Chang' AND 'Longlife Tofu';
4.2.4 Değer Girilmemiş Kayıtların Bulunması
Bir tablo oluşturulduğunda, bazı alanlara değer girilmemesine izin verilebilir. Örneğin bir adres bilgisinde posta kodu alanı opsiyonel olarak bırakılabilir. Bu şekilde hiç bir değer girilmemiş alanlarda saklanan değere NULL değer denir.
Bilgi: NULL ne 0 demektir, ne de boş bir metin bilgisi.
NULL bilgiya ulaşmak için WHERE deyimi ile IS NULL anahtar sözcüğü birlikte kullanılır.
Örnek 4.8: Tedarikçiler (Suppliers) tablosundan fax bilgisi girilmemiş tedarikçilerin listesini alalım.
Sorgu 16:
SELECT SupplierID, CompanyName
FROM Suppliers
WHERE Fax IS NULL;
WHERE Fax IS NULL kodu sayesinde fax numarası girilmemiş tedarikçiler listelenir.
5 - DETAYLI VERİ ARAMA TEKNİKLERİ
Önceki bölümlerde öğrenilen sorgulamanın temel yapılarını birleştirerek daha ileri seviyede ve detaylı sorguların nasıl yapılacağını göreceğiz.
5.1 - WHERE Deyimi ve Kullanımı
WHERE deyiminin temel kullanım şeklini öğrendik. Şimdi ise daha detaylı veri sorgulaması için gereken yöntemleri inceleyeceğiz. Örneğin WHERE deyiminin çeşitli operatörlerle birlikte kullanımına ilişkin teknikler vereceğiz.
5.1.1 AND Operatörü
Birden fazla kolona ait bilgileri sorgulamak için AND operatörü kullanılır. AND operatörü, WHERE deyimi ile birlikte kullanılacaktır.
Örnek 5.1: Satıcı kimlik numarası 8 olan ve fiyatı 40 liradan küçük olan ürünleri listeleyelim.
Sorgu 17:
SELECT SupplierID, ProductName, UnitPrice
FROM Products
WHERE SupplierID = 8 AND UnitPrice <= 40;
Daha önceki örneklerimizde satıcı kimlik numarası 8 olan satıcının ürünlerini listelemek için WHERE SupplierID = 8 kodunu, ve fiyatı 40 liradan küçük olan ürünleri listelemek için ise WHERE UnitPrice <= 40 kodunu kullanmıştır.
Bu sorguda, satıcı kimlik kodu 8 olan ve fiyatı 40 liradan küçük olan ürünleri listelemek istiyorsak bu iki koşulu birleştirmemiz gerekmez mi? İşte bu gibi durumlarda AND operatörü kullanılır. İki farklı kolona ait sorguları birleştirmek için AND operatörünü WHERE deyimi ile birleştiririz.
WHERE SupplierID = 8 AND UnitPrice <= 40;
sorgusu ile istenilen sonuca ulaşılır.
5.1.2 OR Operatörü
AND operatörünün mantıksal değili OR operatörüdür. OR operatörü, birden fazla koşuldan en az birine uyan koşulları listelemek için kullanılır. Kullanımı AND operatörüna oldukça benzer.
Örnek 5.2: Satıcı kimlik kodu 8 ve 10 olan ürünleri listeleyelim.
Sorgu 18:
SELECT SupplierID, ProductName, UnitPrice
FROM Products
WHERE SupplierID=8 OR SupplierID=10
Bu sorguda iki satıcıya ait bilgiler listelendi. Ancak örneğimizde kurduğumuz cümlede satıcı kimlik kodu 8 ve 10 olan satıcılara ait ürünleri listelemek istediğimizi belirttik. Bu cümleyi koda dökerken ise OR operatörünü kullandık, AND değil. Çünkü biz aslında satıcı kodu 8 olan veya satıcı kodu 10 olan satıcılara ait ürünleri listelemek istedik. Burada dikkat edilecek konu, OR operatörünün gerekliliğini anlamaktır.
5.1.3 Sorgularda İşlem Sırası
WHERE deyimi ile AND ve OR operatörlerini birlikte kullanabiliyoruz. WHERE deyimi ile sonsuz sayıda AND ve OR operatörü kullanılabilir. Peki bu operatörlere birleştirilen sorgular hangi sırada işleme sokulur? Bunu bir örnekle açıklayalım.
Örnek 5.3: Satıcı kimlik numarası 8 ve 10 olan satıcılardan alınan ürünler arasından fiyatı 20 lira veya fazla olan ürünleri listeleyelim.
Sorgu 19:
SELECT SupplierID, ProductName, UnitPrice
FROM Products
WHERE SupplierID=8 OR SupplierID=10 AND UnitPrice >=20
Ancak bu sorgu sonucunda göreceğimiz küme, aslında doğru sonuçları içermeyecektir. Bu sorguda fiyatı 20 liradan küçük olan sorgular da gelecektir. Çünkü operatörlerin bir öncelik sırası vardır. SQL de ve çoğu programlama dillerinde AND operatörü önceliğe sahiptir. Yani AND ve OR operatörünün bir arada bulunduğu durumlarda önce AND operatörünün operantları ile işlem yapılır.
Bilgi: Operant, operatörlerin önünde kullanılan değerlerdir.
Bu önceliğin getireceği yanlış sonuçları ortadan kaldırmak için parantezleri kullanacağız.
Sorgu 20:
SELECT SupplierID, ProductName, UnitPrice
FROM Products
WHERE (SupplierID=8 OR SupplierID=10) AND UnitPrice >=20
Parantezlerin kullanılmasıyla önce satıcı kimlik numaralarına göre sorgu yapılacak, sonra bu satıcılara ait ürünler arasından ürün fiyatı 10 liradan büyük olanlar listelenecektir.
5.2 - IN Operatörü
IN operatörü ise, belirli bir aralıktaki verileri kümelek için kullanılır. İki parantez arasında kümenin elemanları virgül ile ayrılarak bildirilir.
Örnek 5.4: Satıcı kimlik kodu 8 ve 10 olan ürünleri IN operatörü kullanarak listeleyelim.
Sorgu 21:
SELECT SupplierID, ProductName, UnitPrice
FROM Products
WHERE SupplierID IN(8, 10)
ORDER BY ProductName
Sorguda da görüldüğü gibi, belirli bir kümeye ait elemanlara ulaşmak için IN operatörü kullanıldı. Bu sorgunun sonuç kümesi Sorgu 18’in sonuç kümesi ile aynı olacaktır. Çünkü IN operatörü gereksiz OR kullanımlarını engellemek için kullanılmıştır.
OR operatörü yerine IN operatörünü kullanarak kodunuzun okunabilirliğini arttırabilirsiniz. Böylece ne yapmak istediğiniz bir başkası tarafından daha kolay anlaşılacaktır.
5.3 - NOT Operatörü
NOT operatörünün sadece bir işlevi vardır. Kendisinden sonra gelen ifadeyi olumsuz yapar. NOT operatörünün kullanımında diğer operatörlerden farklı olarak kolon isimlerinin önüne gelir.
Örnek 5.5: Satıcı kimlik kodu 8 dışındaki tüm satıcıları listeleyelim.
Sorgu 22:
SELECT SupplierID, ProductName
FROM Products
WHERE NOT SupplierID = 8;
Bu sorgunun sonuç kümesi, sorgu 12’nin sonuç kümesi ile aynı olacaktır.
Aslında NOT operatörünün hiçbir avantajı yoktur. Ancak çok karmaşık sorgularda IN operatörüyle belirtilen kümenin dışındaki kayıtlara ulaşmak amacıyla kullanılabilir.
Bilgi: NOT operatörünün bu şekilde kullanımı, MySql veri tabanı yönetim sistemi tarafından desteklenmemektedir. NOT operatörü MySql’de sadece EXISTS anahtar sözcüğünün önüne gelebilir ve ona negatif anlam katar.
6 - Wildcard ile Arama – Filtreleme
Wildcard, metin aramalarında oldukça kolaylık sağlayacak ifadeler içeren karakter arama tekniğidir. Birkaç özel karakterden oluşur.
6.1 - LIKE Operatörü
Bu zamana kadar yaptığımız sorgularda bilinen değerleri aradık. Örneğin fiyatı belirli bir değere aralığında olanlar, adı belirli olan bir ürünü aradık. Şimdi ise tam olarak bilinmeyen değerlere nasıl ulaşacağımızı öğreneceğiz. İçinde food geçen ürünlere ulaşmak istediğimizde, wildcard kullanmak durumundayız.
Bilgi: Arama kriteri (Search pattern), arama ifadeleri ve/veya wildcard karakterleri içeren sorgu metinidir.
SQL ifadelerinde wildcard kullanabilmek için LIKE anahtar sözcüğü gereklidir. WHERE deyimlerinden kullandığımız sorgulardan farklı olarak wildcard ifadelerine karşılık gelen değerlere ulaşırken, istediğimizden daha fazla kayıt karşımıza çıkabilir.
Daha önceden operatör olarak kullanılan karakterler, wildcard ifadesi olarak kullanıldığında tamamen farklı görevlerle yüklenirler.
Wildcard ifadeleri, yalnızca metin veri türü içeren alanların (yani kolonların) sorgularında kullanılabilir.
6.1.1 Yüzde (%) (perdent) Wildcard Karakteri
Wildcard karakterleri arasında en çok kullanılanı, yüzde karakteridir. Anlamı ise bir arama metninde herhangi bir karakterden herhangi bir sayıda bulunabileceğidir. Yani R harfi ile başlayan ürünlerin listesi istendiğinde LIKE anahtar sözcüğü ile % karakteri kombine edilecektir.
Örnek 6.1: R harfi ile başlayan ürünlerin listesini alalım.
Sorgu 23:
SELECT ProductName
FROM Products
WHERE ProductName LIKE 'R%'
Bu sorguda yüzde ifadesinden önce belirtilen karakter veya karakterler ile başlayan kayıtlara ulaşmak istedik. İkinci veya diğer herhangi bir karakter hakkında bir bilgi vermedik. Sonuç kümesi hakkında tek bildiğimiz, sadece ürün adlarının ilk harfinin R olacağıdır.
Önemli Not: Ms Access veri tabanı yönetim sistemi, % karakteri yerine * karakteri kullanır. Yani yukarıdaki sorgu Ms Access’de
SELECT ProductName
FROM Products
WHERE ProductName LIKE 'R*'
şeklinde olacaktır.
Bazı veri tabanı yönerim sistemlerinde büyük harf – küçük harf duyarlılığı vardır. O yüzden arama kriterini belirlerken buna dikkat etmek gerekebilir.
Yüzde karakteri ile bir metinin içinde geçen bir ifadeyi de arayabiliriz.
Örnek 6.2: İçinde Chef geçen ürün isimlerinin listesini alalım.
Sorgu 24:
SELECT ProductName
FROM Products
WHERE ProductName LIKE '%chef%'
Bu sorguda bulunmak istenen, içinde chef geçen ürünlerdir. O yüzden chef sözcüğünün başına ve sonuna birer yüzde karakteri konur ve ilgili kayıtlar listelenir.
Örnek 6.3: S ile başlayan ve s ile biten ürünleri listeleyelim.
Sorgu 25:
SELECT ProductName
FROM Products
WHERE ProductName LIKE 'S*s'
LIKE ‘S*s’ diyerek, sonuç kümem ilk harfi S, aradaki harflerle ve sayısıyla ilgili hiçbir kriter belirtilmesin, ve son harfi yine s olan kayıtları içersin demek istedik.
6.1.2 Alttire (_) (underscore) Wildcard Karakteri
Alttire karakterinin kullanımı da yüzde karakterine oldukça benzemektedir. Ancak yüzde karakterinden en önemli farkı, herhangi sayıda değil de, tek bir karaktere karşılık gelmesidir.
Önemli Not: Ms Access veri tabanı yönetim sisteminde _ yerine ? kullanılır.
Örnek 6.4: Ürün adı Tof ile başlayan ve 4 harften oluşan ürünleri listeleyelim.
Sorgu 26:
SELECT ProductName
FROM Products
WHERE ProductName LIKE 'Tof_'
Ürün adı Tof ile başlıyor ancak son, yani dördüncü karakteri neydi unuttum diyorsak alttire karakteri kullanmalıyız.
Eğer başında ve sonunda birer karakter olan ve arasında bir metin parçası içeren arama yapmak istiyorsak, wildcard ifademizin bir başına bir de sonuna birer alttire kullanacağız demektir.
Örnek 6.5: 5 harfli bir ürün adı var, ilk ve son harflerini bilmiyoruz ancak içinde “kur” sözcüğü geçiyor. Bu ürünün adı nedir?
Sorgu 27:
SELECT ProductName
FROM Products
WHERE ProductName LIKE '_kur_'
Örnek 6.6: Bir ürün var “Cha” ile başlıyor, 5 harfli ve adını hatırlayamadım.
Sorgu 28:
SELECT ProductName
FROM Products
WHERE ProductName LIKE 'Cha__'
Bu sorguda da, her bir karakter için bir alttireyi arama kriterinin içerisine yerleştirdik.
6.1.3 Köşeli Parantez ( [ ] )(brackets) Wildcard Karakteri
Köşeli parantez wildcard karakteri ile çeşitli karakterler bir küme halinde belirtilir. Bu karakter kümesinden herhangi biri eşleşebilir.
Bilgi: Köşeli parantez kullanımını her veri tabanı yönetim sistemi desteklemeyebilir. Access, SQL Server ve Sybase Adaptive Server veri tabanı yönetim sistemlerinin desteklediği bilinmektedir. Diğerleri için özelliklerini incelemenizi tavsiye ederiz.
Örnek 6.7: Müşteriler (Customers) tablosundan R veya T harfleriyle başlayan müşteri isimlerini bulalım.
Sorgu 29:
SELECT ContactName, CompanyName
FROM Customers
WHERE ContactName LIKE '[RT]*'
ORDER BY ContactName
Bu sorguda köşeli parantezler içerisinde belirtilen R ve T harflerinden biriyle başlayan müşteri isimleri görüntülenmiştir. Köşeli parantez içinde listelerken, IN operatöründeki gibi virgüller ile ayırmak sözkonusu değildir.
Bu küme istenildiği kadar genişletilebilir.
Bu sorgunun eşdeğeri sorgu 30’da belirtilmiştir.
Sorgu 30:
SELECT ContactName, CompanyName
FROM Customers
WHERE ContactName LIKE 'R*' OR ContactName LIKE 'T*'
ORDER BY ContactName
Gördüğünüz gibi OR operatörü kullanmak yerine köşeli parantezler ile sorgumuzu daha okunabilir kıldık.
Örnek 6.8: Adı R veya T ile başlamayan müşterilerimizi sorgulayalım.
Sorgu 31:
SELECT ContactName, CompanyName
FROM Customers
WHERE ContactName LIKE '[^RT]%'
ORDER BY ContactName
^ (karat karakteri) sayesinde bir kümenin değili elde edilir. Yani içinde R ve T olmayan elemanların oluşturduğu küme içerisinden değerler gelir.
Bilgi: Ms Access’de ise ^ operatörü yerine ! kullanılır. Yani sorgu 31’in Access’de çalışabilmesi için
SELECT ContactName, CompanyName
FROM Customers
WHERE ContactName LIKE '[!RT]*'
ORDER BY ContactName;
şeklinde kodlanması gerekir.
Karat karakteri (^) yerine NOT operatörünü de kullanabiliriz.
Sorgu 32:
SELECT ContactName, CompanyName
FROM Customers
WHERE NOT ContactName LIKE '[RT]%'
ORDER BY ContactName;
Karat karakteri kullandığımızda R ve T dışındaki elemanların oluşturduğu kümeyi elde ettiğimizi belirtmiştik. NOT operatörü ise aynı görevi yapar ve R ve T ile başlamayan tüm kayıtlara ulaştır.
Wildcard kullanmaya karar vermeden önce iki kere düşünün:
• Aynı işlevi bir operatör ile yapabiliyorsanız, bu sorgu performansını arttıracaktır. Çünkü wildcard ile arama yapmak, en yavaş çalışan görevdir.
• Wildcard karakterlerini kullanırken çok dikkatli olunuz. İstemeyerek yanlış sonuçlar elde edilebilir.
7 - TABLONUN ALANLARI İLE ÇALIŞMAK
Tablolarda bulunan kolonlar dışında, çeşitli hesaplamalar yapılarak yeni sonuçlar elde edilebilir.
7.1 Tabloların Alanları ile Neden Çalışılır?
Tablolar, bilgileri kolonlar halinde saklar. Ve bir veri tabanında çoğu bilgiler, küçük parçalara ayrıştırılarak saklanır. Ve kimi zaman bu kolonlardaki bilgilerin birleşitirilmesi gerekir. Belki de bu alanlar üzerinde çeşitli hesaplamaların da yapılması gerekebilir.
Örneğin;
• Bir müşterinin adı, soyadı ve bulunduğu şehri bir arada görüntülemek
• Adresi oluşturan kolonları birleştirerek tam adres oluşturmak
• Ürünleri ve isimlerini birlikte görüntülemek
vs.
Görüntülemek istediğimiz veriler, istenilen formatta değilse, onları biz istediğimiz şekilde görüntüleyebiliriz.
Bilgi: Tablonun kolonlarını kastederek, alan dediğimiz durumlar da olacaktır.
7.2 Alanların Birleştirilmesi
Alanlar ile yapacağımız ilk işlem, iki alanı bir kolonda birleştirmek olacaktır.
Örnek 7.1: Tedarikçiler (Suppliers) tablosundan tedarikçi adını ve bulunduğu ülkeyi bir arada bulunduracak sorguyu oluşturalım.
Sorgu 33:
SELECT CompanyName + ' (' + Country + ') '
FROM Suppliers
Burada tedarikçiler tablosundan tedarikçi şirketin adı ve bulunduğu ülkenin bilgisi + operatörü ile birleşitirilerek sonuca varılmıştır.
Yapılan işlemleri sıralayacak olursak;
• CompanyName kolonunda bulunan bilgi alınır
• Bir boşluk ve bir parantezden oluşan metin ifadesi eklenir.
• Sonra Country kolonunda bulunan bilgi de alınıp eklenir.
• Ve son olarak da bir parantez ve bir boşluk karakterleri de eklenir.
Bilgi: Ms Access, SQL Server ve Sybase veri tabanı yönetim sistemleri, metin ekleme işlemleri için + operatörünü desteklerler. DB2, Oracle, PostgreSQL ve Sybase ise metin ekleme işlemleri için || (pipe) operatörünü destekler.
MySql ise, metin ekleme işlemleri için bu iki operatörden hiçbirini desteklemez. Bu işlem için CONCAT() fonksiyonu tanımlanmıştır. MySql’de || operatörü OR operatörü ile aynı anlamdadır.
SELECT CONCAT(CompanyName, ‘( ‘, Country, ‘
’ )
Bazı veri tabanı yönetim sistemlerinde alanlar birleştirilirken aralara istenmeyen boşluklar gelebilir. Bu durum, veri tabanı sistemlerinin kolonun maksimum karakter sayısına göre yerleştirmesinden kaynaklanır. İstenmeyen boşlukları kaldırmak için, RTRIM(), LTRIM() ve TRIM() SQL fonksiyonları kullanılabilir.
Sorgu 34:
SELECT RTRIM(CompanyName) + ' (' + RTRIM(Country) + ') '
FROM Suppliers
ORDER BY CompanyName
RTRIM sağdaki, LTRIM soldaki ve TRIM hem baştaki hem de sondaki boşlukları yok eder.
7.2.1 Kolon İsimlerinde Takma Ad Kullanımı (Alias)
Birleştirilen alanların oluşturduğu yeni kolona ait bir kolon ismi tanımlamak için AS anahtar sözcüğü kullanılır.
Örnek 7.2: Tedarikçiler (Suppliers) tablosundan tedarikçi adını ve bulunduğu ülkeyi bir arada bulunduracak sorguyu oluşturalım. Ve yeni oluşan kolona “Supplier_Name” adı verelim.
Sorgu 35:
SELECT RTRIM(CompanyName)+' ('+RTRIM(Country)+') '
AS Supplier_Name
FROM Suppliers
ORDER BY CompanyName
Sorguda da görüldüğü gibi, oluşturulan bu yeni kolona Supplier_Name adı verilmiştir. Dikkat ettiyseniz bir metin ifadesini ayırmak için kullanılan tek tırnakları burada kullanmadık.
7.2.2 Matematiksel İfadelerin Hesaplanması
Aslında alanlar üzerinde en çok yapılan işlemler matematiksel işlemlerdir. Sipariş detaylarına ilişkin verilerin tutulduğu “Order Details” tablosu üzerinde çeşitli işlemler yapılabilir.
Örnek 7.3: 10840 numaralı ürüne ait siparişlerin detaylarını görüntüleyelim.
Sorgu 36:
SELECT ProductID, Quantity, UnitPrice
FROM [Order Details]
WHERE OrderID = 10840
Bu sorgu sonucunda UnitPrice, her bir ürün için geçerli olan fiyatları gösterir. Peki ya bu siparişin toplam tutarını görüntülemek için ne yapılmalı?
Sorgu 37:
SELECT ProductID, Quantity,
UnitPrice, Quantity * UnitPrice AS Total_Price
FROM [Order Details]
WHERE OrderID = 10840
Sorgu sonucunda da görüldüğü gibi, mevcut kolonlardaki bilgiler kullanılarak yeni veriler elde edilmek isteniyorsa, SELECT deyiminin içerisinde bu işlemler tanımlanabilir. Bu alanlarda istenilen tüm matematiksel hesaplamalar yapılabilir.
8 - Veriler Üzerinde Değişiklik Yapan Fonksiyonlar
Veri tabanı yönetim sistemleri tarafından desteklenen SQL fonksiyonlarını öğreneceğiz.
8.1 - Fonksiyonlar Üzerine
SQL içerisinde dei programlama dillerinde olduğu gibi veriler üzerinde işlem yapmaya yarayan standart fonksiyonlar vardır.
Bir önceki konuda TRIM, LTRIM ve RTRIM fonksiyonlarından bahsetmiştik. Aslında fonksiyon kullanmak kimi zaman da işleri oldukça ağırlaştırmaktadır. Örneğin SELECT deyimi standart bir deyimken, fonksiyonlar standart değildir. Tablo 8.1’de veri tabanı yönetim sistemlerinin fonksiyonları arasındaki farklılıklar belirtilmiştir.
Fonksiyon Söz dizimi
Bir metnin bir kısmından yeni bir metin oluşturmak Ms Access MID(), DB2, Oracle ve PostgreSQL SUBSTR(), Ms SQL Server, MySQL ve Sybase ise SUBSTRING() fonksiyolarını kullanır.
Tür Dönüştürme DB2 ve PostgreSQL CAST(), MySQL, Sql Server ve Sybase CONVERT() fonksiyonlarını kullanır. Access ve Oracle her dönüşüm türüne göre bir fonksiyon kullanır.
Tarih Alma Access NOW(), DB2 ve PostgreSQL CURRENT_DATE, MySQL CURDATE(), Oracle SYSDATE, Sql Server ve Sybase GETDATE() fonksiyonlarını kullanır.
Tablo 8.1: Veri Tabanı Yönetim Sistemlerinde Bazı Fonksiyonlar ve Farklılıkları
Tablo 8.1’den de görüldüğü gibi, SQL fonksiyonları kullanmak o kadar da avantajlı değildir. Çünkü bir sistemde yazılmış kod, diğer bir sistemde çalışamayabilir. Yani taşınabilir değildir.
8.2 – Fonksiyon Kullanımı
Fonksiyonlar, yaptığı işlevlere göre gruplandırılabilir. Örneğin metin üzerinde işlemler yapan fonksiyonlar, nümerik işlem yapan fonksiyonlar, zaman ve tarih fonksiyonları ve sistem fonksiyonları olarak gruplandırılabilir.
8.2.1 Metinler Üzerinde İşlem Yapan Fonksiyonlar
Önceki bölümde gördüğümüz TRIM() fonksiyonları, bu gruba dahildir. Örneğin ele alınan metini tamamen küçük harfe dönüştüren LOWER() ve büyük harfe dönüştüren UPPER() fonksiyonları da bu gruptadır.
Örnek 8.1: Sorgu 33’deki sorgumuzun sonuçlarını tamamen büyük harflerle görüntüleyelim.
Sorgu 38:
SELECT UPPER(CompanyName) + ' (' + UPPER(Country) + ') '
FROM Suppliers
ORDER BY CompanyName
UPPER() fonksiyonu ile tüm karakterler büyük harfe dönüştürüldü. Tamamen küçük harfe dönüştürmek isteseydik LOWER() fonksiyonunu kullanacaktır. Sıklıkla kullanılan metinsel veriler üzerinde değişiklik yapan fonksiyonlar tablo 8.2’de gösterilmiştir.
Fonksiyon Açıklama
LEFT() Metinin sol tarafından karakter alır
RIGHT() Metinin sağ tarafından karakter adır
LENGHT(), Access’de LEN() Metinin uzunluğunu verir
LOWER(), Access’de LCASE() Metini tamamen küçük harflere dönüştürür
UPPER(), Access’de UCASE() Metini tamamen büyük harflere dönüştürür
LTRIM() Metinin solundaki boşlukları kaldırır
RTRIM() Metinin sağındaki boşlukları kaldırır
TRIM() Metinin başındaki ve sonundaki boşlukları kaldırır
SOUNDEX() Bir metinin SOUNDEX değerini geri döndürür
Tablo 8.2: Metin üzerinde değişiklik yapan Fonksiyonlar
Tablo 8.2’de belirtilen fonksiyonlardan SOUNDEX fonksiyonu, diğerlerinden çok farklı bür göreve sahiptir. SOUNDEX, bir metni, bu metinin fonetik karşılığını içeren alfanümerik başka bir metine dönüştüren bir algoritmadır. SQL ile doğrudan bir ilişkisi olmamasına rağmen pek çok veri tabanı yönetim sistemi bu algoritmayı destekler. Ms Access ve PostgreSQL desteklemez.
SOUNDEX kullanımına bir örnek verelim.
Örnek 8.2: Richter Supermarkt isimli müşterimizin “Michael Holz” adında bir kontağı olsun. Ya aslında bu kişinin adı “Michelle Holz” olduğu halde aynı şekilde söylendiğinden dolayı yanlış yazılmışsa?
Sorgu 39: değştirrr
SELECT CompanyName, ContactName
FROM Customers
WHERE ContactName = ‘Michelle Holz’
Bu sorgu elbette boş bir kümeyle geri dönecektir. SOUNDEX fonksiyonunu kullanırsak...
Sorgu 40:
SELECT CompanyName, ContactName
FROM Customers
WHERE SOUNDEX(ContactName) = SOUNDEX(‘Michelle Holz’
Örnekte de görüldüğü gibi hem ContactName alanı, hem de bu alanda arana değer SOUNDEX() fonksiyonu ile SOUNDEX değerine dönüştürülüp o şekilde arama yapılmış. Ve böylede ilgili kayıda ulaşılmıştır.
8.2.2 Tarih ve Zaman Üzerinde İşlem Yapan Fonksiyonlar
Her bir veri tabanı yönetim sisteminin kendine has tarih ve zaman bilgilerini saklama yöntemi vardır. Tabiki bizi ilgilendiren bu verilerin nasıl tutulacağı ve nasıl ulaşılacağıdır.
Tarih ve zaman bilgisini ayrıştıran çeşitli fonksiyonlar vardır.
Örnek 8.3: 1996 yılına ait tüm siparişleri listeleyelim.
Sorgu 41:
SELECT OrderID
FROM Orders
WHERE DATEPART(yy, OrderDate) = 1996
Bilgi: Ms Access’de DATEPART fonksiyonunun kullanımında bir farklılık vardır.
SELECT OrderID
FROM Orders
WHERE DATEPART('yyyy',OrderDate)=1996;
şeklinde belirtmek gerekir. Bu formu SQL Server ve Sybase de destekler. MySql ise
SELECT OrderID
FROM Orders
WHERE YEAR(OrderDate)=1996;
şeklide destekler. Oracle ise
SELECT OrderID
FROM Orders
WHERE to_number(to_char(OrderDate, ‘YY’
)=1996;
şeklinde destekler.
Örnek 8.4: 1 Ocak 1996 ile 1 Ocak 1998 tarihleri arasındaki siparişleri listelemek isteyelim.
Sorgu 42:
SELECT OrderID, OrderDate
FROM Orders
WHERE OrderDate Between ‘1/1/1996’ And ‘1/1/1998’
Bilgi: Ms Access’de tarih belirtirken # işareti kullanılır.
WHERE OrderDate Between #1/1/1996# And #1/1/1998#
8.2.3 Nümerik İşlem Yapan Fonksiyonlar
Nümerik veriler üzerinde çeşitli cebirsel işlem yapan fonksiyonlardır. Metin ve tarih fonksiyonları kadar çok kullanılmazlar.
Tablo 8.3’de nümerik fonksiyonlar listelenmiştir.
Fonksiyon Açıklama
ABS() Sayının mutlak değerini verir
COS() Belirtilen açının trigonometrik kosinüs değerini verir
SIN() Belirtilen açının trigonometrik sinüs değerini verir
TAN() Belirtilen açının trigonometrik tanjant değerini verir
EXP() Belirtilen sayının exp üstel değerini verir
SQRT() Belirtilen sayının karekök değerini verir
PI() Pi sayısını verir
Tablo 8.3: Nümerik Fonksiyonlar
9 - Veriler Üzerinden Özet Bilgi Alınması
Tabloların kolonlarında saklanan verilere ilişkin özet bilgi elde edebilemek için SQL’in çeşitli toplam fonksiyonlarından (aggregate functions) yararlanacağız.
Bilgi: Aggregate Functions (toplam fonksiyonları), kolonlar üzerinde toplam değer, ortalama değer gibi bilgileri geri döndüren işlemleri yapan fonksiyonlardır.
9.1 Toplam Fonksiyonlarının Kullanımı
Tablolarda saklanan veriler üzerinde sıklıkla gerçekleşen işlemler için tasarlanmış fonksiyonların nasıl kullanıldığını inceleyelim.
Bir veri tabanından istenen bilgilerin başında;
• Bir tablodaki kayıt sayısını elde etmek
• Belirli bir koşulu sağlayan kayıtların sayısını elde etmek
• Tablonun kolonlarındaki verilerin toplamını elde etmek
• Kolonlara ait en yüksek, en düşük ve ortalama değerleri elde etmek
gelir. Bu gibi işlemler gerçekleştirmek için beş adet toplam fonksiyonu tasarlanmıştır. Tablo 9.1’de toplam fonksiyonları listelenmiştir.
Fonksiyon Açıklama
AVG() Kolona ait ortalama değer
COUNT() Kolondaki satır sayısı
MAX() Kolondaki en yüksek değer
MIN() Kolondaki en düşük değer
SUM() Kolondaki değerlerin toplamı
Tablo 9.1: Toplam Fonksiyonları (Aggregate Functions)
9.1.1 AVG() Fonksiyonu
Tablonun belirli bir kolonuna ait veriler üzerinde, o kolondaki tüm değerlerin toplanıp değer girilen satırların sayısına bölümünden elde edilen ortalama değeri geri döndürür. Yani değer girilmemiş satırlar işleme sokulmaz.
Örnek 9.1: Ortalama ürün fiyat bilgisini almak isteyelim.
Sorgu 43:
SELECT AVG(UnitPrice) AS Ortalama_Fiyat
FROM Products
Sorgudan da görüldüğü gibi, hesaplama yapılacak kolon ismi AVG() fonksiyonunun parantezleri içerisinde bildirildi. Ve hesaplanan bu değere Ortalama_Fiyat adında yeni bir kolon ismi verildi.
Örnek 9.2: Tedarikçi kayıt numarası 3 olan ürünlerin ortalama fiyat bilgisine ulaşmak isteyelim.
Sorgu 44:
SELECT AVG(UnitPrice) AS Ortalama_Fiyat
FROM Products
WHERE SupplierID = 3
Bu sorguda ise belirli bir kritere göre gelen sonuç kümesi üzerinde ortalama işlemi yapılmıştır.
AVG() fonksiyonu sadece nümerik değerler içeren kolon üzerinde işlem yapar ve bu kolon adı fonksiyon parametresinde belirtilmelidir. Ayrıca birden fazla kolona ait ortalama değeri elde etmek için elbette birden fazla AVG() fonksiyonu kullanılmalıdır.
Bilgi: NULL değer içeren satırlar, AVG() fonksiyonu tarafından işleme sokulmaz.
9.1.2 COUNT() Fonksiyonu
Adından da anlaşılacağı gibi COUNT() fonksiyonu, belirli bir kolondaki kayıtları sayar. Bu fonksiyonun iki farklı kullanım şekli vardır.
• COUNT(*) ile, tablodaki kayıt sayısı elde edilir. NULL değerler de sayılır.
• COUNT (kolon_adı) ile, NULL değer içeren satırlar işlem dışı tutularak belirli bir kolondaki kayıt sayısı elde edilir.
Örnek 9.3: Kaç tane müşterimiz var acaba?
Sorgu 45:
SELECT COUNT(*) AS Müşteri_Sayısı
FROM Customers
COUNT(*) kullanılan sorgularda satır içerisinde veri girilip girilmediğine bakılmadan toplam satır sayısı geri döndürülür.
Örnek 9.4: Fax numarası girilmiş kaç tane müşterimiz var acaba?
Sorgu 46:
SELECT COUNT(Fax) AS Faxlı_Müşteri_Sayısı
FROM Customers
COUNT(kolon_adı) kullanılan sorgularda kolona ait veriler girilmişse sayım yapılır. Yani NULL değer içeren kayıtlar sayılmaz.
9.1.3 MAX() Fonksiyonu
MAX() fonksiyonu, belirtilen kolondaki en büyük değere ait veriyi geri döndürür.
Örnek 9.5: En yüksek fiyatlı ürünü öğrenmek isteyelim.
Sorgu 47:
SELECT MAX(UnitPrice) AS Maksimum_Fiyat
FROM Products
Bu örnekte en pahalı ürün görüntülenmiştir.
MAX() fonksiyonu nümerik değerlerin yanı sıra, zaman, tarih ve metinsel ifadelerde de kullanılır. Çoğu veri tabanı yönetim sistemi bunu destekler. Örneğin metinsel ifadeler içeren bir kolona MAX() fonksiyonu uygulanırsa alfabedeki sıralamaya göre en son sıraya düşen kayıt görüntülenir.
Örnek 9.6: Alfabetik listeye göre en sonda yer alan müşteriyi görüntüleyelim.
Sorgu 48:
SELECT MAX(CompanyName) AS En_Sondaki_Müşteri
FROM Customers
MAX() fonksiyonu NULL değer içeren kayıtlar ile işlem yapmaz.
9.1.4 MIN() Fonksiyonu
MIN() fonksiyonu, belirtilen kolondaki en küçük değere ait veriyi geri döndürür.
Örnek 9.7: En düşük fiyatlı ürünü öğrenmek isteyelim.
Sorgu 49:
SELECT MIN(UnitPrice) AS Minimum_Fiyat
FROM Products
Bu örnekte en ucuz ürün görüntülenmiştir.
MIN() fonksiyonu nümerik değerlerin yanı sıra, zaman, tarih ve metinsel ifadelerde de kullanılır. Çoğu veri tabanı yönetim sistemi bunu destekler. Örneğin metinsel ifadeler içeren bir kolona MIN() fonksiyonu uygulanırsa alfabedeki sıralamaya göre en öndeki kayıt görüntülenir.
9.1.5 SUM() Fonksiyonu
SUM() fonksiyonu, belirtilen kolondaki değerlerin toplamını geri döndürür.
Örnek 9.10: Toplam kaç adet malın sipariş verildiğini bulalım.
Sorgu 50:
SELECT SUM(Quantity) AS Toplam_Ürün
FROM [Order Details]
Bu örnekte Order Details tablosu baştan sona dolaşılmış ve Quantity kolondaki tüm değerler toplanmıştır.
Örnek 9.11: 10255 numaralı siparişte toplam kaç adet malın sipariş verildiğini bulalım.
Sorgu 51:
SELECT SUM(Quantity) AS Toplam_Ürün
FROM [Order Details]
WHERE OrderID = 10255
Bu örnekte ise 10255 numaralı siparişe ait kayıtlardaki Quantity kolonuna ait değerler toplanmıştır.
Örnek 9.12: 10255 numaralı siparişten elde edilecek tutarı bulalım.
Sorgu 52:
SELECT SUM(Quantity * UnitPrice) AS Tutar
FROM [Order Details]
WHERE OrderID = 10255
Sorgudan da görüldüğü gibi, önce Quantity ile UnitPrice verileri çarpılarak her bir siparişin tutarı hesaplandı. Ve bu alan SUM() fonksiyonu ile toplam tutar elde edildi.
Toplam fonksiyonları sayesinde farklı kolonlara ait matematiksel işlemler gerçekleştirilebilir.
NULL değer içeren kayıtlar da SUM() fonksiyonu tarafından işleme sokulmazlar.
9.2 - Farklı Değerler Üzerinde Toplam İşlemleri
Toplam fonksiyonları ile yaptığımız işlemler tüm kayıtlar üzerinde gerçekleştirildi. ALL anahtar sözcüğü kullanılmasa da, aslında toplam fonksiyonlar içerisinde varsayılan değer olarak ALL anahtar sözcüğünün kullanılmıştır. DISTINCT anahtar sözcüğü ise, aynı değere ait kayıtlardan sadece birer tanesinin işleme koyulacağını belirtir.
Bilgi: ALL değeri, varsayılan değerdir. Yani toplam fonksiyonlarında hiçbir değer belirtilmezse, ALL değeri kullanılmış kabul edilir.
Ancak, MS Access veri tabanı yönetim sistemi, toplam fonksiyonlarında DISTINCT anahtar sözcüğünü desteklemez.
Örnek 9.13: 15 kayıt numaralı tedarikçiye ait ürünlerin tekil değerilerinin ortalama fiyatını almak isteyelim.
Sorgu 53:
SELECT AVG(DISTINCT UnitPrice) AS tekil_ortalama_deger
FROM Products WHERE SupplierID = 15
Burada her bir fiyat değeri sadece bir kere işleme sokulmuştur. Yani aynı fiyattaki ürünler sadece bir kez toplanır. Ve tabiki ortalama değer bu şekilde hesaplanır.
kaç farklı ülke ile çalıışıldı ekle
DISTINCT anahtar sözcüğü COUNT(*) fonksiyonu ile kullanılamaz. Ancak kolon adı belirtilerek COUNT(kolon_adı) şeklinde kullanılabilir.
9.3 - Toplam Fonksiyonlarının Beraber Kullanımı
Toplam fonksiyonları ile yaptığımız örnekler bunların birer birer kullanılmasıyla ilgiliydi. Şimdi ise aynı ifadede birden fazla toplam fonksiyonunun nasıl kullanıldığına bakacağız.
Örnek 9.14: Ürünler tablosunda, ürün sayısını, en düşük, en yüksek fiyatı ve ortalama değeri gösterelim.
Sorgu 54:
SELECT
COUNT(*) AS Ürün_Sayısı,
MIN(UnitPrice) AS En_Düşük,
MAX(UnitPrice) AS En_Yüksek,
AVG(UnitPrice) AS Ortalama_Deger
FROM Products
Sorgudan da görüldüğü gibi ürün fiyatlarına ilişkin kolona dört adet toplam fonksiyonu uygulanmıştır.
10 - Verilerin Gruplandırılması
Tablolara ait içerikler üzerinde verileri nasıl gruplandırılacağını göreceğiz. Bu durumda SELECT deyiminin yanında, GROUP BY ve HAVING deyimlerini kullanacağız.
10.1 - Veri Gruplama Nedir?
SQL toplam fonksiyonları sayesinde verilere ait çeşitli özet bilgileri elde etmeyi öğrendik. Bu sorgular belirli bir değere ilişkin verileri içermişti. Şimdi ise verileri belirli bir kritere göre gruplayarak toplam fonksiyonlarını nasıl kullanacağımızı öğreneceğiz.
Örnek 10.1: 4 kayıt numaralı tedarikçiye ait ürünlerin sayısını öğrenelim.
Sorgu 55:
SELECT COUNT(*) AS Ürün_Sayısı
FROM Products
WHERE SupplierID = 4
Bu örnekte 4 numaralı tedakçiden gelen ürünlerin sayısını aldık. Peki her bir tedarikçiden gelen ürünlerin sayısını ayrı ayrı olarak öğrenmek istesek ne yapacağız?
10.2 - Grup Oluşturmak
Gruplar, SELECT ifadesi ile GROUP BY deyiminin birleşmesiyle oluşur.
Örnek 10.2: Her bir tedarikçiden gelen ürünlerin sayısını ayrı ayrı görüntülemek isteyelim.
Sorgu 56:
SELECT SupplierID, COUNT(*) AS Ürün_Sayısı
FROM Products
GROUP BY SupplierID
Bu sorgunun sonucunda, her bir tedarikçi ve bu tedarikçilere ait ürün sayısı bilgisi listelenmiştir. GROUP BY deyimi ile belirtilen kolon adına göre kayıtlar ayrıştırılır, sonra SELECT ifadesinde belirtilen COUNT(*) fonksiyonu, sayımı yapar ve görüntüler.
Yani kayıtlar, GROUP BY ile belirtilen kolon sayısındaki farklı veriler kadar sayıda satır oluşacak ve her bir kayıtta kaç adet ürün bulunduğu da hemen yanındaki kolonda görüntülenecektir.
GROUP BY deyimini kullanmadan önce, şu bilgileri göz önünde bulundurmalıyız:
• İstenildiği kadar sayıda GROUP BY deyimi iç içe kullanılabilir.
• GROUP BY deyimi kullanıldığında, toplam fonksiyonu SELECT ifadesinin en son alanında bildirilmelidir.
• GROUP BY deyiminde belirtilen ifade, ya geçerli bir kolon adı olmalıdır, ya da toplam fonksiyonları dışında geçerli bir ifade olması gerekir.
• GROUP BY deyiminin nümerik değer içeren kolonlara uygulanması gereklidir.
• Gruplandırılacak kolonda NULL değer varsa, NULL değeri de bir grup değeri olarak ayrılır. Birden fazla NULL değeri içeren kayıt varsa, hepsi bir grupta toparlanır.
• GROUP BY deyimi WHERE anahtar sözcüğünden sonra ve ORDER BY deyiminden önce gelmelidir.
10.3 - Grup Üzerinde Filtreleme Yapmak
GROUP BY ile veri gruplarken hangi verilerin gruba katılacağı veya ayrı tutulacağı da belirtilebilir. Örneğin, toplam sipariş miktarı 1200 adetten fazla olan ürün kodlarının görüntülenmesini isteyelim. O zaman her bir kayıtlar üzerinde tek tek değil, gruplar üzerinde filtreleme yapılacaktır.
WHERE deyimini biliyoruz. Ancak bu durumda WHERE deyimi işe yaramayacaktır. Çünkü WHERE deyimi kayıtlat üzerinde filtreleme yapabilirken, gruplar üzerinde filtreleme yapamayacaktır. Peki WHERE deyiminin yerini tutacak olan şey nedir? HAVING yan cümlesidir. WHERE deyimi ile kullandığımız tüm işlemleri HAVING yan cümlesi ile de kullanabileceğiz.
Örnek 10.3: Toplam sipariş miktarı 1200 adetten fazla olan ürün kodları listelenmiştir.
Sorgu 57:
SELECT ProductID, SUM(Quantity) AS total_quantity
FROM [Order Details]
GROUP BY ProductID
HAVING SUM(Quantity) > 1200
Sorguda da görüldüğü gibi, SELECT ifadesinde kullanılan ProductID ve Quantity alanları, GROUP BY ve HAVING deyimleri ile de birleştirilmiştir. Sorguyu sondan başa doğru okursak, sipariş miktarı 1200’den fazla olan ürünleri al, ProductID değerine göre grupla gibi bir cümle çıkar.
Örnek 10.4: 100’den fazla müşteriden sipariş alan çalışanları, müşteri sayısına göre gruplayarak listeleyelim.
Sorgu 58:
SELECT EmployeeID, COUNT(CustomerID) AS Müşteri_Sayısı
FROM Orders
GROUP BY EmployeeID
HAVING COUNT(CustomerID)>100
ORDER BY EmployeeID
Sorguda da görüldüğü gibi, SELECT ifadesinde kullanılan EmployeeID ve CustomerID alanları, GROUP BY ve HAVING deyimleri ile de birleştirilmiştir.
Örnek 10.5: Onaltı veya daha fazla sipariş veren müşterileri listeleyelim.
Sorgu 59:
SELECT CustomerID, COUNT(*) AS Siparişler
FROM Orders
GROUP BY CustomerID
HAVING COUNT(*) >= 16
Örneklerden de görüldüğü gibi, WHERE ve HAVING anahtar sözcükleri arasındaki en büyük fark; WHERE deyimi veri gruplandırılmadan önce filtreleme yapar, HAVING ise veriyi gruplandırdıktan sonra filtreleme yapar.
WHERE ve HAVING deyimlerinin birlikte kullanıldığı durumlar da olacaktır.
Örnek 10.6: 15 lira ve daha yukarı fiyata sahip ürünleri tedarikçilerine göre gruplandırarak listeleyelim.
Sorgu 60:
SELECT SupplierID, COUNT(*) AS Ürün_Sayısı
FROM Products
WHERE UnitPrice >= 15
GROUP BY SupplierID
HAVING COUNT(*) >=1
10.4 SELECT İfadesinin İşlem Sırası
Öğrendiğimiz deyimlerin bir arada kullanılmasına ilişkin bir tablo tanımlayalım.
Deyim Açıklama Gereklilik
SELECT Geri döndürelecek kolon veya ifadeler Evet
FROM Veri alınacak tablo Sadece tablodan veri seçimi yapılacağı durumlarda gerekli
WHERE Filtreleme Hayır
GROUP BY Grup tanımalam Gruplar ile toplam fonksiyonlarının kullanıldığı durumda
HAVING Grup filtrelemesinde Hayır
ORDER BY Sıralanarak görüntüleme Hayır
Tablo 10.1: Deyimlerin Kullanım Sırası
11 - Alt Sorgular
Bu bölümde alt sorgular ile çalışacağız.
11.1 Alt Sorgu Nedir?
Bu zamana kadar çalıştığımız örnekler sadece bir sorgu üzerinde gelen verileri içeriyordu.
Bilgi: Sorgu, herhangi bir SQL ifadesine denir.
Alt sorgu ise, bir sorgu içinda başka bir sorgunun yer alması durumudur. Alt sorgulara neden ihtiyaç duyulduğu ileriki örneklerde göreceğiz.
Bilgi: MySQL kullanıcıları, 4.1’den önceki versiyonlar alt sorguları desteklemez.
11.2 Alt Sorgular ile Filtreleme
Kullandığımız Northwind veritabanı, tabloları arasında ilişkiler kurulmuş bir veri tabanıdır. Siparişlere ait bilgiler iki tabloda saklanmıştır. Orders, siparişi veren müşteriye ve zamana ait bilgileri tutar. Order Details tablosu ise bu sipariş içindeki ürünleri, adedini, fiyat ve indirim bilgilerini tutar. Müşterilere ilişkin veriler ise Customers tablosunda tutuldu, Order ve Order Details tablolarında müşteriye ait kimlik numarasına referans verildi.
Örneğin 37 numaralı ürünü sipariş veren tüm müşterileri listelemek için neler yapılmalıdır?
1 – 37 numaralı ürünü içeren tüm siparişleri getir.
2 – Bir önceki adım sonucu gelen kümenin içerisinden müşteri kimlik numaraları alınır.
3 – Her bir müşterinin bilgisini bu şekilde al.
Bu olayları gerçekleşitirmek için 2 ayrı sorgu tasarlayabiliriz.
Örnek 11.1: 37 numaralı ürüne ait siparişlerin sipariş numaralarını getirelim.
Sorgu 61:
SELECT OrderID FROM [Order Details]
WHERE ProductID = 37
Şimdi ise 61 numaralı sorgunun sonuç kümesindeki her bir eleman için müşteri kimlik numaralarını almamız gerekir. Bu sorgunun sonuç kümesi, 10259, 10337, 10408, 10523, 10847, 10966 den oluşur.
Örnek 11.2: 61 numaralı sorgunun sonuç kümesindeki müşterilerin kimlik numaralarını alalım.
Sorgu 62:
SELECT CustomerID FROM Orders
WHERE OrderID IN(10259, 10337, 10408, 10523, 10847, 10966)
Peki bu iki ayrı sorguyu birlikte kullanarak daha verimli bir sorgu oluşturmak için ne yapmalıyız?
Örnek 11.3: 37 numaralı ürünü sipariş veren tüm müşterileri listelemek isteyelim.
Sorgu 63:
SELECT CustomerID
FROM Orders
WHERE OrderID
IN ( SELECT OrderID FROM [Order Details] WHERE ProductID = 37)
Bu sorguda ilk önce içeride bildirdiğimiz sorgu çalıştırılacak, bu sorgudan oluşan sonuç kümesi içerisindeki bilgiler ise diğer sorguya veri olarak aktarılır. Yani önce
“SELECT OrderID FROM [Order Details] WHERE ProductID = 37”
sorgusu çalıştırılır. Bu sorgu sonucunda (10259, 10337, 10408, 10523, 10847, 10966) verileri gelir. Daha sonra ise bu siparişleri veren müşteri numaralarına erişmek için
“SELECT CustomerID FROM Orders
WHERE OrderID IN ( içteki sorgu sonucu)”
sorgusu çalıştırılır.
İşleme her zaman en içteki sorgudan başlanır.
Bu sorgular sonucunda müşteri numaralarını elde ettik. Müşteri numarasına göre ayrıntılı bilgi almak için ise Örnek 11.4’e bakalım.
Örnek 11.4: 37 numaralı ürünü sipariş veren her bir müşterinin adını ve kontak ismini alalım.
Sorgu 64:
SELECT CompanyName, ContactName
FROM Customers
WHERE CustomerID IN
(SELECT CustomerID FROM Orders WHERE OrderID IN
(SELECT OrderID FROM [Order Details]
WHERE productID = 37))
Bu sorguda iç içe iki sorgu ile sonuca ulaşılmıştır. Gördüğünüz gibi önce 37 numaralı ürüne ait sipariş numaraları, sonra bu numaralı siparişleri veren müşterilerin kayıt numaraları, ve en sonunda ise bu numaralara sahip müşterilerin iletişim bilgileri alınır.
11.3 Alt Sorguları Hesaplanmış Alanlar Olarak Kullanmak
Alt sorguları kullanmanın bir diğer yolu ise, hesaplanmış alanlar içinde alt sorgulara yer vermektir. Örneğin, Customers tablosunda her bir müşterinin verdiği toplam sipariş miktarını görüntülemek isteyelim. Biliyoruz ki siparişlerin hepsi Orders tablosunda tutulur ve OrderID anahtar değeri ile ulaşılır.
Örnek 11.5: Her bir müşteri tarafından verilen sipariş miktarını görüntüleyen sorgu oluşturalım.
Bu işlemi gerçekleştirmek için şu adımları gerçekleştirmeliyiz:
1- Customers tablosundan müşterilerin listesi gelir
2- Her bir müşteri için, Orders tablosunda verilen siparişler hesaplanır
Biliyoruz ki bir tablodaki kayıtları saymak için SELECT COUNT(*) deyimi kullanılır, WHERE yan cümlesi ile her bir müşteri numarası için sipariş bilgilerini ulaşılır. Örneğin kodu ‘CACTU’ olan müşteriye ait siparişleri listelemek için
Sorgu 65:
SELECT COUNT(*) AS Toplam_Siparis
FROM Orders
WHERE CustomerID = 'CACTU'
sorgusu kullanılır. Ancak görüyoruz ki bu sorgu sadece CACTU kodlu müşteriye ait siparişleri listeler. Biz bu sorguyu her bir müşteri için elde etmek istesek ne yapmamız gerekir? İşte burada işimiz biraz daha karmaşıklaşacak. SELECT COUNT(*) sorgusunu alt sorgu olarak kullanmamız gerekecek.
Sorgu 66:
SELECT CompanyName, Country,
(SELECT COUNT(*) FROM ORDERS
WHERE Orders.CustomerID = Customers.CustomerID)
AS Toplam_Siparisler
FROM Customers
ORDER BY CompanyName
Daha önce kullanmadığımız bir biçimde sorgu kalıbı kullandık.
Olayı şöyle canlandıralım:
CompanyName, Country alalarının yanında bir de bu şirketlerden gelen toplam sipariş sayısını öğrenmek istiyoruz. Bu kolonu oluşturmak için bir iç sorgu yapıyoruz.
(SELECT COUNT(*) FROM Orders
WHERE Orders.CustomerID = Customers.CustomerID
AS Toplam_Siparisler)
İşte bu sorgu, her bir şirket için verilen sipariş sayısını hesaplar. Peki nasıl? Dikkat ettiyseniz WHERE yan cümlesinden sonra Orders ve Customers tablolarının CustomerID alanları birbirlerine bağlanmış, yani ilişkilendirilmiş. Eğer burada
Orders.CustomerID = Customers.CustomerID
ifadesi kullanılmasaydı bu işlem gerçekleşmezdi.
12 – Tabloları Birleştirme
Bu bölümde tabloları birleştirerek yep yeni sorgular oluşturacağız.
12.1 Tablolar Arası Veri Birleştirme Nedir?
SQL’in en güzel ve en güçlü yönlerinden biri, sorguların çalıştırıldığı zaman birden fazla tabloya ait verilerin bir sonuç kümesi içinde görüntülenebilmesidir. Burada pek çok şeye dikkat etmemiz gerekecek. Hangi tablonun tekil anahtar değeri (primary key) ile hangi tablonun foreign key değerlerinin birleştirilmesi gerektiği bilgileri iyice belirlenmelidir.
Aslında verinin nasıl birleştirileceğinden önce ilişkisel tablolar üzerinde biraz bilgi tazelemesi yapmak gerekiyor.
Örneğin veri tabanımızda ürün kataloğu içeren bir veri tablomuz var. Her bir katalog ürünü ise kendi sırasında yer almakta. Her bir ürüne ait tanımlama, fiyat, tedarikçi bilgisi gibi verileri de bulundurmamız gerekir.
Peki, aynı tedarikçiye ait ürünlerimiz varsa ne olacak? Tedarikçi bilgilerini nerede tutacağız? Tabiki her bir ürün için tek tek bu bilgileri girmemiz gereksiz olacak.
İşte bu gibi durumlarda veriler, parçalanabilecek en küçük parçalara ayrıştırılacak, tablolara bölüştürülecek, ve bu tablolar birbirleriyle ilişkilendirilecektir.
Bu örneğimizde Products, Suppliers tablolarını ele alırsak, her bir tedarikçiye bir tekil kimlik numarası (ID) verilecek ve Products tablosunda ise her bir ürünün tedarikçi alanına ise tedarikçi adı değil, kimlik numarası girilecektir.
12.2 Tablolar Arası Veri Nasıl Birleştirilir (Join)?
Aslında join işlemi oldukça basittir. Veri getirilecek tüm tabloların isimleri ve bu tabloların hangi alanlar vasıtasıyla birleştirileceği bilgisi belirtilmelidir.
Örnek 12.1: Ürünlerimize ait tedarikçi firma adı, ürün adı ve fiyatını görüntüleyelim.
Sorgu 67:
SELECT CompanyName, ProductName, UnitPrice
FROM Suppliers, Products
WHERE Suppliers.SupplierID = Products.SupplierID
Sonuç kümesini incelersek, Suppliers tablosundan CompanyName, ve Products tablosundan ProductName, UnitPrice alanlarının getirildiğini görürüz. Burada en önemli olay, bu iki tablonun SupplierID alanları ile birleştirilebiliyor olmasıdır. Suppliers tablosundaki SupplierID tekil anahtar (primary key) ve Products tablosundaki SupplierID ise foreign key vazifesindedir.
SELECT anahtar sözcüğü ve WHERE yan cümlesini iki farklı tablodan veri alıp birleştirmek için kullandık. İlişkili tablolardan veri almak için gerekli olan, WHERE yan cümlesinden sonra bu tablolar arasında ilişki kuracak alanın belirtilmesidir.
Aslında bu sorguyu şu şekilde yeniden yazarsak, aynı kolon adına sahip olabilecek tablolarda sorun çıkmasını engelleriz.
Sorgu 68:
SELECT Suppliers.CompanyName,
Products.ProductName, Products.UnitPrice
FROM Suppliers, Products
WHERE Suppliers.SupplierID = Products.SupplierID
12.3 WHERE Yan Cümlesinin Önemi
İki tablo arasındaki ilişkiyi belirtmek için WHERE yan cümlesini kullanıyor olmamız ilk başta biraz tuhaf gelebilir. SELECT ifadesinde belirtilen ilişkiler, sorgu çalıştığı zaman kurulur ve görüntülenir.
WHERE yan cümlesinden sonra belirtilen tablolar arası ilişki ifadesi, unutulursa istenilenden fazla sayıda sonuç görüntüler.
Sorgu 69:
SELECT CompanyName, ProductName, UnitPrice
FROM Suppliers, Products
Bu sonuç kümesi oldukça kalabalık değil mi? Sebebi ise, Suppliers tablosundaki kayıtlar ile Products tablosundaki kayıtların kartezyen çarpılmasıdır. Yani Suppliers tablosundaki bir kayıt, Products tablosundaki tüm kayıtlarla birer birer eşleşir. Yani sonuç kümesindeki eleman sayısı (Suppliers tablosundaki kayıt sayısı) * (Products tablosundaki kayıt sayısı) na eşittir.
İşte bu gereksiz eşleşmeleri önlemek için WHERE yan cümlesinden sonra Suppliers.SupplierID = Products.SupplierID ifadesi kullanılır. Tekrar belirtmeliyiz ki, iki tablo arasındaki ilişkiyi belirtmek için tekil anahtar olan değeri tablo adı ile birleştirip, foreign key olarak kullanılacak alanı bu tablo adı ile birleştiririz.
12.4 INNER JOIN
Bir önceki konuda iki tablo arasında kurduğumuz birleştirme ilişkisine “equijoin” denir. Yani iki tablo arasında eşitliğin test edilmesi ile oluşturulan join.
Şimdi biraz daha farklı bir sentaks kullanacağız.
Örnek 12.2: Ürünlerimize ait tedarikçi firma adı, ürün adı ve fiyatını görüntüleyelim.
Sorgu 70:
SELECT CompanyName, ProductName, UnitPrice
FROM Suppliers INNER JOIN Products
ON Suppliers.SupplierID = Products.SupplierID
İşte tablolar arasındaki ilişkiler için INNER JOIN anahtar sözcüğünü kullanmamız daha yararlı olacaktır.
Sorguyu incelersek, hangi tablodan hangi tabloya ilişki kurulacağı FROM anahtar sözcüğünden sonra belirtilir.
Hatırlayacağınız gibi Suppliers tablosunda her bir tedarikçiye verilen numaralar SupplierID alanında tutuluyordu (primary key). Products tablosunda ise ürünün hangi tedarikçiye ait olduğu bilgisi yine SupplierID alanında tutuluyordu (foreign key).
Bu iki alan arasında ON anahtar sözcüğü kullanılır.
INNER JOIN Products ON Suppliers.SupplierID = Products.SupplierID
Burada kullanılan INNER JOIN ve ON anahtar sözcükleri, daha önce kullandığımız WHERE
Suppliers.SupplierID = Products.SupplierID ile oluşturulan ilişki yerine kullanılır.İlişkinin yönü belirtildiği için bu tarz kullanım önerilmektedir.
İki tablo arasında ilişki kurmak için WHERE geçerli olsa da, çoklu tablolarda o kadar da kolay olmayacaktır.
12.5 Çoklu Tabloları JOIN ile Birleştirmek
SELECT ifadesi içerisinde istenildiği kadar tablo arasında ilişki kurulabilir. SQL bunun için bir sınır belirlememiştir. Olay aslında o kadar da karmaşık değildir. Yapılması gereken, öncelikle tüm tablolar listelenir ve sonra birbirleri arasındaki ilişki tanımlanır.
Örnek 12.3: 10274 numaralı siparişe ait ayrıntılı bilgi almak istiyoruz.
Sorgu 71:
SELECT Products.ProductName, Suppliers.CompanyName,
[Order Details].UnitPrice,[Order Details].Quantity
FROM [Order Details], Products, Suppliers
WHERE Products.SupplierID = Suppliers.SupplierID
AND
[Order Details].ProductID = Products.ProductID
AND OrderID = 10274
Unutmayalım ki sorguyu incelemek istiyorsak, cümleyi okumaya en sondan başlamalıyız. Bu sorguda, Order Details tablosundan 10274 numaralı sipariş ele alınır. Bu kayıt üzerinden UnitPrice ve Quantity bilgisinin yanında Products tablosuna ulaşılır ve ProductName bilgisi alınır. Aynı şekilde Suppliers tablosundan CompanyName bilgisi alınır.
Aslında bu sorgu, alt sorgular kullanılarak da çalıştırılabilirdi.
Örnek 12.4: 9 numaralı ürünü sipariş veren müşterilere ait ayrıntılı bilgi almak istiyoruz.
Sorgu 72:
SELECT CompanyName, ContactName FROM Customers
WHERE CustomerID IN
(SELECT CustomerID FROM Orders WHERE OrderID IN
(SELECT OrderID FROM [Order Details]
WHERE ProductID = 9))
Sonuca ulaşmak için hangi yolun kullanılacağı tamamen sizin deneyimlerinize dayanmaktadır. Önemli olan doğru veriye ulaşmak. Sorgu 73 bu sonucu farklı yöntemle görüntüler.
Sorgu 73:
SELECT CompanyName, ContactName
FROM Customers, Orders, [Order Details]
WHERE Customers.CustomerID = Orders.CustomerID
AND [Order Details].OrderID = Orders.OrderID
AND ProductID = 9
13 – İleri Seviyede Tabloları Birleştirme
Bu bölümde tabloları birleştirme işleminde daha ileri seviyede işlemler nasıl yapılır inceleyeceğiz. Toplam fonksiyonlarını joinler içinde nasıl kullanılacağını da göreceğiz.
13.1 Tablolara Yeni Adlar Vermek (Using Aliases)
Önceki bölümlerde hesaplanan alanlara yeni isimler verildiğini öğrenmiştik.
SELECT CompanyName + ‘ (‘ + Country + ‘
’ AS Supplier_Title
FROM Suppliers ORDER BY CompanyName
Alanlara yeni isimler vermenin yanı sıra, tablolara da yeni isimler verebiliriz. Tablolara yeni isim verme ihtiyacı neden duyulur?
• SQL sentaksını kısaltmak
• Tek bir SELECT ifadesinde aynı tabloyu birden fazla kez kullanmak
Örnek 13.1: 9 numaralı ürünü sipariş veren müşterilere ait ayrıntılı bilgileri alalım.
Sorgu 74:
SELECT CompanyName, ContactName
FROM Customers AS C, Orders AS O, [Order Details] AS OD
WHERE C.CustomerID = O.CustomerID
AND OD.OrderID = O.OrderID
AND ProductID = 9
Sorgudan da görüldüğü gibi 3 tablodan veri alıp birleştirildi. C dediğimiz şey aslında Customers tablosunun yerini tuttu. C.CustomerID ise, Customers.CustomerID ile eşittir.
Bilgi: Oracle, AS anahtar sözcüğünü desteklemez. Customers AS C yerine, Customer C kullanılır.
Alan adlarında kullanılan yeni isimler görüntülenir, ancak tablolarda böyle bir durum yoktur. Yani kullanıcı bu isimleri görmez.
13.2 Farklı JOIN Türlerinin Kullanımı
INNER JOIN ve equijoin kavramlarını gördük. Şimdi ise üç farklı join türü inceleyeceğiz.
13.2.1 Self Join (Kendisiyle İlişkilendirmek)
Tablolara yeniden isim vermek hakkında bahsettiğimiz gibi, aynı sorgu içinde aynı tablo adını birden fazla kullanmamızın gerektiği durumlar olacaktır.
alıntıdır
Veri tabanı ile bilgi alış verişi yapılmasını sağlayan bir dildir. Ancak SQL yalnız başına bir dil olarak algılanmamalıdır. Çünkü SQL, programlama dillerinin içine gömülen kodlar sayesinde çalışır. Kullanıldığı işletim sisteminin API (Application Programming Interface) fonksiyonlarını çalıştırır, ancak programcının bundan haberi olmaz.
Programlama dillerinin İngilizcesidir. Birkaç İngilizce kelimeden oluşur. Veri tabanı sorgusu yapan dile aslında T-SQL (Transact SQL) denir. SQL denince program değil, programlama dillerinde kullanılan sorgulama ara dili akla gelmelidir. Veri tabanlarını görüntülemeye ve yönetmeye yarayan programlara ise “Veri tabanı yönetim sistemi (Database Management System)” denir.
Piyasada pek çok veri tabanı yönetim sistemi vardır. Bunlardan en çok bilinenleri
• Microsoft SQL Server
• Oracle
• My-Sql
• Microsoft Access
• Informix
Çeşitli programlama dilleri gibi, SQL de standart hale getirilmiştir. ANSI tarafından standart hale getirilmiş ANSI SQL, her bir veri tabanı yönetim sistemi tarafından desteklenmesi gereken bir standarttır.
Veri Tabanı (Database)
Günümüzde veri tabanı (database), neredeyse her alanda kullanılmaktadır. Adres defterinizden bir adresi araştırmanız bile bir veri tabanı sorgusudur. Arama motorları sayesinde ulaştığınız bilgiler de yine veri tabanları ile haberleşir.
Bilgi: Veri tabanı, verileri derli toplu olarak saklamaya yarayan dosya ve dosyalar kümesidir.
Bilgi: Yaygın olarak veri tabanı yazılımlarına hatalı bir kullanışla “veritabanı” adı kullanılır. Ancak o programlar veri tabanı değil, veri tabanı yönetim sistemleridir (Database Management System). Veri tabanları bu yazılımlar sayesinde de kullanılabilir.
Tablolar (Tables)
Veri tabanında bilgilerin saklandığı alt birimlere tablo denir. Bir veri tabanında pek çok bilgi saklanabilir. Ancak bunların belirli bir şekilde ayrılması gerekir. Örneğin bir okulun tüm öğrencilerinin ve tüm notlarının tek bir tablo içerisinde tutulması karmaşaya yol açacaktır. Bu durumda veriler tablolara ayrılır. Ve tablolar birbirleriyle ilişkilendirilir.
Bir veri tabanında aynı isimde iki tablo bulunamaz. Tabi ki farklı veri tabanlarında aynı isimde tablolar bulunabilir.
Bilgi: Veri tabanına ait tabloların özelliklerini ve yerleşim şekillerini içeren bilgiye şema (schema) denir.
Kolonlar ve Veri Türleri (Columns and Datatypes)
Veri tabanının tablolardan oluştuğunu belirtmiştik. Tablolar da kolonlardan oluşur. Kolonlar, her birinde aynı türden veri saklayan birimlerdir. Örneğin öğrenci bilgilerini saklayan bir tabloda, bir kolon öğrenci numarasını, bir kolon adını ve diğer bir kolon da soyadını tutar. Yani her bir özelleşmiş bilgi, bir kolonda saklanır.
Verileri ayrı ayrı kolonlarda tutmak da çok önemlidir. Örneğin aynı isime sahip öğrencilere ulaşmak istendiğinde, eğer ad ve soyad bilgisi aynı kolonda tutulmuşsa işlem karmaşıklaşacaktır. Ancak ad ve soyad ayrı ayrı kolonlarda tutulmuşsa, işlem oldukça kolay olacaktır.
Her bir kolonun, saklayacağı bilginin özelliğini belirten veri türü bulunmaktadır. Bu veri türü sayesinde o kolonda saklanacak bilgi sınırlanır. Örneğin sayısal ifadelerin yer alacağı bir kolona karakter girilmesinin yasaklanması gibi.
Bilgi: Veri tabanlarınsa saklanacak bilgilerin türlerini belirten veri türleri, farklı veri tabanı yönetim sistemlerinde farklı isimlere sahip olabilirler. İşte bu farklılık, veri tabanı uyumu konusunda uyumsuzluk oluşturan en temel konudur. Aslında temel veri türleri aynı isimle kullanılsa da, özel veri türleri oldukça farklıdır.
Satırlar (Rows)
Bir tablodaki bilgiler satırlarda saklanır. Her bir kayıt kendi sırasında tutulur. Yine Excel tablolarını gözünüzde canlandırırsanız, dikey kolonlar tabloların kolonlarına, yatay satırlar ise tabloların satırlarına karşılık geldiğini görürsünüz.
Bilgi: Bir satır, bir kayıt (record) demektir.
Tekil Anahtarlar (Primary Keys)
Her bir tabloda, tablonun özelliğini taşıyan özel bir veya birden fazla kolon bulundurmalıdır. Örneğin öğrenci tablosunda, öğrenci numarasını tutan kolon bu tablodaki tekil bilgiyi tutar. O zaman tasarım sırasında öğrenci numarasını tutan kolon, tekil anahtar olarak belirtilmelidir.
Tekil anahtar kullanarak aynı kolonda farklı satırlarda aynı bilginin girilmesi engellenmiş olur. Ve bu kolona veri girilmemesi gibi bir durum söz konusu olamaz. (NULL değer kabul edilmez.) Tekil anahtar olarak belirlenen kolonların değiştirlmemesi gerekir.
2 - Veriye Ulaşmak
Bir tablodan bir veya birden fazla kolona ait bilgiye ulaşabilmek için SELECT ifadesi kullanılır.
2.1 - SELECT İfadesi
SQL’in birkaç İngilizce kelimeden oluştuğunu belirtmiştik. Aslında bu kelimelere anahtar sözcük denir. Tablolardan bilgi almak için SELECT anahtar sözcüğü kullanılır.
Bilgi: Anahtar sözcük, diğer programlama dillerinde olduğu gibi SQL’de de “reserverd keywords” yani değişken adı olarak kullanılması yasaklanmış sözcüklerdir. Örneğin SELECT adında bir tablo veya kolon kullanmamak gerekir.
Bir tablodan veri almak için iki bilgiye ihtiyaç vardır: Hangi tablodan ve hangi kolondan alınacağı.
SELECT ifadesinin sözdizimi (sentax):
SELECT <kolon ad(lar)ı> FROM <tablo adı>
Örnek 2.1: Ürünler tablosunda bulunan tüm ürünlerin adının listesini almak isteyelim.
Sorgu 1:
SELECT ProductName
FROM Products;
Ürünler tablosundan urun_adi olarak isimlendirilmiş kolondaki bilgilere ulaşmak için SELECT sorgusu kullanıldı.
Bilgi: Bir sorgudan elde edilen bilgiler topluluğuna “sonuç kümesi” denir.
Sonuç kümesinde görüntülenen veriler, veri tabanına girilişe göre listelenmiştir. Yani bir sıralama söz konusu değildir. İleride sıralanmış bilgiyi elde edebileceğiz.
SQL ifadeleri, aralarında istenildiği kadar boşluk kullanılarak çalıştırılabilir.
SQL’de büyük harf küçük harf duyarlılığı, veri tabanı yönetim sistemine göre değişir.
Bir tablodan birden fazla kolona ait bilgi almak için kolon adları arasına virgül konulur.
Örnek 2.2: Ürünler tablosunda bulunan ürünlerin kodunu, adını ve fiyatlarını listelemek isteyelim.
Sorgu 2 :
SELECT ProductID, ProductName, UnitPrice
FROM Products;
Ürünler tablosundan almak istediğimiz kolonarı birbirinden virgül ile ayırdık.
Bir tabloya ait tüm kolonların bilgisini almak için ise * operatörü kullanılır.
Örnek 2.3: Ürünler tablosundaki tüm bilgileri görüntülemek isteyelim.
Sorgu 3:
SELECT *
FROM Products
Sorguda * operatörü kullanınca, tablodaki tüm kolonlar görüntülenir. Sıralanması ise tabloda bulunduğu gibidir.
3 - Verilerin Sıralanması
SELECT sorgusu ile ORDER BY deyimini kullanarak sonuç kümesindeki verileri sıralamayı inceleyeceğiz.
3.1 - Sıralama İşlemi
Sonuç kümesindeki verileri istenilen kritere göre sıralamak için ORDER BY deyimini kullanacağız.
Bilgi: SQL ifadelerinde sorguları kuvvetlendirmek için çeşitli kalıplar kullanılır. Bu kalıplara deyim (clause) da denebilir.
ORDER BY Sözdizimi:
SELECT <kolon ad(lar)ı> FROM <tablo adı>
ORDER BY <kolon adı>
Örnek 3.1: Ürünler tablosundan alfabetik sıralı olarak ürün adlarını listeleyelim.
Sorgu 4:
SELECT ProductName
FROM Products
ORDER BY ProductName;
Bu sorgunun diğer sorgularımızdan farkı, ürün isimlerine göre sıralandırma yapabiliyor olmasıdır. Tablo ismi belirtildikten sonra hangi kolona göre sıralandırma yapılmak isteniyorsa ORDER BY deyiminden sonra o kolonun adı belirtilir. Burada dikkat edilmesi gereken, ORDER BY deyiminin en sonda kullanılıyor olmasıdır.
Görüntülenmek istenen kolonlara göre sıralama yaptırılacağına göre, SELECT listemizde yer almayan bir kolona göre sıralama yaptırmak pek kullanışlı olmayacaktır.
3.2 - Çoklu Kolonlara Göre Sıralama
Bazı durumlarda tek bir sıralama kriteri yeterli olmaz. Örneğin bir personel tablosunda soyada göre sıralanıp listenenen personelin bir de adına göre sıralanması istenebilir. Aynı soyada sahip işçiler için bu durum söz konusudur.
Çoklu kolona göre sıralama yapmak için, tıpkı çoklu kolon bilgilerini görüntülerken kolon isimleri arasına konulan virgüller gibi ORDER BY deyiminden sonra da kolonlar arasına virgül koymak gerekir.
Örnek 3.2: Ürünler tablosunda ürün kodu, fiyatı ve ismini, önce fiyata göre, sonra da ürün adına göre görüntülemek isteyelim.
Sorgu 5:
SELECT ProductName, UnitPrice
FROM Products
ORDER BY UnitPrice, ProductName;
Birden fazla kolona göre sıralama yapıldığı durumlarda, eğer ilk kritere göre sıralanan kayıtlarda aynı değere sahip kayıt varsa, ikinci kritere göre sıralama yapılır. Yani fiyatı 45 Ytl olan birden fazla ürün varsa, bu ürünler de kendi aralarında ürün adına göre sıralanacaktır.
3.3 - Kolon Pozisyonuna Göre Sıralama
ORDER BY deyiminden sonra kolon isimlerini sıralamak yerine, kolonun pozisyonuna göre de sıralama yapılabilir.
Örnek 3.3: Ürünler tablosunda ürün kodu, fiyatı ve ismini, önce fiyata göre, sonra da ürün adına göre görüntülemek isteyelim. Ancak sıralamada kolon adları yerine pozisyonları kullanalım.
Sorgu 6:
SELECT ProductID, ProductName, UnitPrice
FROM Products
ORDER BY 2, 3;
ORDER BY 2, SELECT listesinde belirtilen ikinci kolon adına göre sıralama yapılacağı anlamına gelir. ORDER BY 2, 3 ifadesinin eşdeğeri,
ORDER BY UnitPrice, ProductName
ifadesidir.
Kolon pozisyonu belirterek yeniden kodlamadan uzakaşmış olunur. Ancak pozisyona karşılık gelen isimlere dönüp bakmak da bazı durumlarda oldukça zaman kaybettirebilir.
3.4 - Sıralama Yönünün Belirtilmesi
Verilerin varsayılan sıralama yönü azdan çoğa artan (ascending) şekildedir. ORDER BY deyiminde hiçbir yön belirtilmezse bu artan olarak algılanır. Artan yönde sıralamak için ASC anahtar sözcüğü kullanılır. Azalan yönde (descending) sıralamak için ise DESC anahtar sözcüğü kullanılır.
Örnek 3.4: Ürünler tablosunu fiyata göre azalan sırada listeleyelim.
Sorgu 7:
SELECT ProductID, UnitPrice, ProductName
FROM Products
ORDER BY UnitPrice DESC;
Bu sorguda tabiki aynı değere sahip kayıtlar kendi aralarında sıralanma kriteri belirtilmeden rastgelen listelenmiştir.
Örnek 3.5: Ürünler tablosunu fiyata göre azalan sırada, sonra da ürün adına göre sıralı listeleyelim.
Sorgu 8:
SELECT ProductID, UnitPrice, ProductName
FROM Products
ORDER BY UnitPrice DESC, ProductName;
Bu sorguda aynı değere sahip kayıtlar kendi aralarında artan yönde sıralanmıştır.
4 - Veri Filtreleme - Arama
WHERE deyimi kullanılarak veriler arasında çeşitli kriterlere göre sorgu yapmayı öğreneceğiz.
4.1 - WHERE Deyiminin Kullanımı
Tablodaki veriler arasında belirli kritere uygun sorgu yapmak için WHERE deyimi kullanılır. Arama kriteri veya filteleme ifadesi olarak da isimlendirilebilir.
WHERE deyimi, FROM ifadesinin hemen sağında kullanılır.
WHERE Söz dizimi:
SELECT <kolon ad(lar)ı> FROM <tablo adı>
WHERE <kolon adı ve koşulu>
Örnek 4.1: Ürünler tablosudan ürün fiyatı 2.5 olanları listelemek isteyelim.
Sorgu 9:
SELECT ProductName, UnitPrice
FROM Products
WHERE UnitPrice = 2.5
Bu sorguda, ürünler tablosundan sadece ürün fiyatı 2.5 olan kayıtlar listelenecektir.
4.2 - WHERE Deyiminde Kullanılacak Operatörler
WHERE deyimi ile kombine edilebilecek çeşitli operatörler vardır. Bu operatörler tablo 4.1’de listelenmiştir.
Operatör Açıklama
= Eşitlik
<> Eşit değil
!= Eşit değil
< Küçüktür
> Büyüktür
<= Küçük eşittir
>= Büyük eşittir
!< Küçük değildir
!> Büyük değildir
BETWEEN İki değer arasında
IS NULL NULL Değer
Tablo 4.1: Where Deyimi Operatörleri
Bu operatörlerden bazıları birbirleriyle aynı anlama gelmektedir. Örneğin <> ile !=, !< ile >=, ve !> ile <= aynı etkileri oluşturur. Fakat bunların hepsi bazı veri tabanı yönetim sistemleri tarafından desteklenmez. Örneğin !=, !< ve !> operatörleri, Ms Access tarafından desteklenmez.
4.2.1 Tek Bir Değere Göre Arama
Önceki örnekte 2.5 liraya eşitliğe göre arama yaptık. Şimdi ise belirli bir fiyattan daha küçük fiyata sahip olanları listeleyelim.
Örnek 4.2: Ürünler tablosundan fiyatı 5 liradan küçük olanları listeleyelim.
Sorgu 10:
SELECT ProductName, UnitPrice
FROM Products
WHERE UnitPrice < 5
Örnek 4.3: Ürünler tablosundan fiyatı 15 liradan büyük ve eşit olanları listeleyelim.
Sorgu 11:
SELECT ProductName, UnitPrice
FROM Products
WHERE UnitPrice >= 15;
4.2.2 Eşitsizlik Durumları
Şimdi ise eşitsizlik durumlarını inceleyelim.
Örnek 4.4: Satıcı numarası 4 olan hariç tüm satıclardan alınan ürünleri listelemek isteyelim.
Sorgu 12:
SELECT SupplierID, ProductName
FROM Products
WHERE (SupplierID <> 4);
Örnek 4.5: Ürün adı Chang dışındaki tüm ürünleri listeleyelim.
Sorgu 13:
SELECT ProductName
FROM Products
WHERE ProductName <> 'Chang'
Örnekten de gördüğünüz gibi, metinsel ifadeler ile ilgili sorgu yaparken ayıraç olarak tekli tırnak kullanılır.
4.2.3 Belirli Bir Değer Aralığındaki Verilerin Araştırılması
Belirli bir değer aralığındaki verileri araştırmak için BETWEEN operatörü kullanılır. Bu operatörün kullanımı WHERE deyiminden biraz daha farklıdır. Arama yapılacak aralığın başlangıcı BETWEEN anahtar sözcüğünden sonra belirtilmeli ve AND anahtar sözcüğünden sonra ise aralığın bitiş noktası belirtilmelidir.
Örnek 4.6: Fiyatı 10 ve 20 lira arasında değişen ürünleri listeleyelim.
Sorgu 14:
SELECT ProductName , UnitPrice
FROM Products
WHERE UnitPrice BETWEEN 10 and 20
BETWEEN operatörü sayesinde istenilen her aralıkta bulunan verileri ulaşabilirsiniz. Önemli olan başlangıç ve bitiş aralığını belirtmektir. Örnekte fiyat araması için nümerik değerler kullanıldı. Ayrıca metin ifadeleri için de aralık belirtilebilir. Bu sefer metinin alfabetik duruma göre arama yapılacaktır.
Örnek 4.7: Ürün adı “Chang” ile “Longlife Tofu” arasında yer alan ürünleri listeleyelim.
Sorgu 15:
SELECT ProductName, UnitPrice
FROM Products
WHERE ProductName BETWEEN 'Chang' AND 'Longlife Tofu';
4.2.4 Değer Girilmemiş Kayıtların Bulunması
Bir tablo oluşturulduğunda, bazı alanlara değer girilmemesine izin verilebilir. Örneğin bir adres bilgisinde posta kodu alanı opsiyonel olarak bırakılabilir. Bu şekilde hiç bir değer girilmemiş alanlarda saklanan değere NULL değer denir.
Bilgi: NULL ne 0 demektir, ne de boş bir metin bilgisi.
NULL bilgiya ulaşmak için WHERE deyimi ile IS NULL anahtar sözcüğü birlikte kullanılır.
Örnek 4.8: Tedarikçiler (Suppliers) tablosundan fax bilgisi girilmemiş tedarikçilerin listesini alalım.
Sorgu 16:
SELECT SupplierID, CompanyName
FROM Suppliers
WHERE Fax IS NULL;
WHERE Fax IS NULL kodu sayesinde fax numarası girilmemiş tedarikçiler listelenir.
5 - DETAYLI VERİ ARAMA TEKNİKLERİ
Önceki bölümlerde öğrenilen sorgulamanın temel yapılarını birleştirerek daha ileri seviyede ve detaylı sorguların nasıl yapılacağını göreceğiz.
5.1 - WHERE Deyimi ve Kullanımı
WHERE deyiminin temel kullanım şeklini öğrendik. Şimdi ise daha detaylı veri sorgulaması için gereken yöntemleri inceleyeceğiz. Örneğin WHERE deyiminin çeşitli operatörlerle birlikte kullanımına ilişkin teknikler vereceğiz.
5.1.1 AND Operatörü
Birden fazla kolona ait bilgileri sorgulamak için AND operatörü kullanılır. AND operatörü, WHERE deyimi ile birlikte kullanılacaktır.
Örnek 5.1: Satıcı kimlik numarası 8 olan ve fiyatı 40 liradan küçük olan ürünleri listeleyelim.
Sorgu 17:
SELECT SupplierID, ProductName, UnitPrice
FROM Products
WHERE SupplierID = 8 AND UnitPrice <= 40;
Daha önceki örneklerimizde satıcı kimlik numarası 8 olan satıcının ürünlerini listelemek için WHERE SupplierID = 8 kodunu, ve fiyatı 40 liradan küçük olan ürünleri listelemek için ise WHERE UnitPrice <= 40 kodunu kullanmıştır.
Bu sorguda, satıcı kimlik kodu 8 olan ve fiyatı 40 liradan küçük olan ürünleri listelemek istiyorsak bu iki koşulu birleştirmemiz gerekmez mi? İşte bu gibi durumlarda AND operatörü kullanılır. İki farklı kolona ait sorguları birleştirmek için AND operatörünü WHERE deyimi ile birleştiririz.
WHERE SupplierID = 8 AND UnitPrice <= 40;
sorgusu ile istenilen sonuca ulaşılır.
5.1.2 OR Operatörü
AND operatörünün mantıksal değili OR operatörüdür. OR operatörü, birden fazla koşuldan en az birine uyan koşulları listelemek için kullanılır. Kullanımı AND operatörüna oldukça benzer.
Örnek 5.2: Satıcı kimlik kodu 8 ve 10 olan ürünleri listeleyelim.
Sorgu 18:
SELECT SupplierID, ProductName, UnitPrice
FROM Products
WHERE SupplierID=8 OR SupplierID=10
Bu sorguda iki satıcıya ait bilgiler listelendi. Ancak örneğimizde kurduğumuz cümlede satıcı kimlik kodu 8 ve 10 olan satıcılara ait ürünleri listelemek istediğimizi belirttik. Bu cümleyi koda dökerken ise OR operatörünü kullandık, AND değil. Çünkü biz aslında satıcı kodu 8 olan veya satıcı kodu 10 olan satıcılara ait ürünleri listelemek istedik. Burada dikkat edilecek konu, OR operatörünün gerekliliğini anlamaktır.
5.1.3 Sorgularda İşlem Sırası
WHERE deyimi ile AND ve OR operatörlerini birlikte kullanabiliyoruz. WHERE deyimi ile sonsuz sayıda AND ve OR operatörü kullanılabilir. Peki bu operatörlere birleştirilen sorgular hangi sırada işleme sokulur? Bunu bir örnekle açıklayalım.
Örnek 5.3: Satıcı kimlik numarası 8 ve 10 olan satıcılardan alınan ürünler arasından fiyatı 20 lira veya fazla olan ürünleri listeleyelim.
Sorgu 19:
SELECT SupplierID, ProductName, UnitPrice
FROM Products
WHERE SupplierID=8 OR SupplierID=10 AND UnitPrice >=20
Ancak bu sorgu sonucunda göreceğimiz küme, aslında doğru sonuçları içermeyecektir. Bu sorguda fiyatı 20 liradan küçük olan sorgular da gelecektir. Çünkü operatörlerin bir öncelik sırası vardır. SQL de ve çoğu programlama dillerinde AND operatörü önceliğe sahiptir. Yani AND ve OR operatörünün bir arada bulunduğu durumlarda önce AND operatörünün operantları ile işlem yapılır.
Bilgi: Operant, operatörlerin önünde kullanılan değerlerdir.
Bu önceliğin getireceği yanlış sonuçları ortadan kaldırmak için parantezleri kullanacağız.
Sorgu 20:
SELECT SupplierID, ProductName, UnitPrice
FROM Products
WHERE (SupplierID=8 OR SupplierID=10) AND UnitPrice >=20
Parantezlerin kullanılmasıyla önce satıcı kimlik numaralarına göre sorgu yapılacak, sonra bu satıcılara ait ürünler arasından ürün fiyatı 10 liradan büyük olanlar listelenecektir.
5.2 - IN Operatörü
IN operatörü ise, belirli bir aralıktaki verileri kümelek için kullanılır. İki parantez arasında kümenin elemanları virgül ile ayrılarak bildirilir.
Örnek 5.4: Satıcı kimlik kodu 8 ve 10 olan ürünleri IN operatörü kullanarak listeleyelim.
Sorgu 21:
SELECT SupplierID, ProductName, UnitPrice
FROM Products
WHERE SupplierID IN(8, 10)
ORDER BY ProductName
Sorguda da görüldüğü gibi, belirli bir kümeye ait elemanlara ulaşmak için IN operatörü kullanıldı. Bu sorgunun sonuç kümesi Sorgu 18’in sonuç kümesi ile aynı olacaktır. Çünkü IN operatörü gereksiz OR kullanımlarını engellemek için kullanılmıştır.
OR operatörü yerine IN operatörünü kullanarak kodunuzun okunabilirliğini arttırabilirsiniz. Böylece ne yapmak istediğiniz bir başkası tarafından daha kolay anlaşılacaktır.
5.3 - NOT Operatörü
NOT operatörünün sadece bir işlevi vardır. Kendisinden sonra gelen ifadeyi olumsuz yapar. NOT operatörünün kullanımında diğer operatörlerden farklı olarak kolon isimlerinin önüne gelir.
Örnek 5.5: Satıcı kimlik kodu 8 dışındaki tüm satıcıları listeleyelim.
Sorgu 22:
SELECT SupplierID, ProductName
FROM Products
WHERE NOT SupplierID = 8;
Bu sorgunun sonuç kümesi, sorgu 12’nin sonuç kümesi ile aynı olacaktır.
Aslında NOT operatörünün hiçbir avantajı yoktur. Ancak çok karmaşık sorgularda IN operatörüyle belirtilen kümenin dışındaki kayıtlara ulaşmak amacıyla kullanılabilir.
Bilgi: NOT operatörünün bu şekilde kullanımı, MySql veri tabanı yönetim sistemi tarafından desteklenmemektedir. NOT operatörü MySql’de sadece EXISTS anahtar sözcüğünün önüne gelebilir ve ona negatif anlam katar.
6 - Wildcard ile Arama – Filtreleme
Wildcard, metin aramalarında oldukça kolaylık sağlayacak ifadeler içeren karakter arama tekniğidir. Birkaç özel karakterden oluşur.
6.1 - LIKE Operatörü
Bu zamana kadar yaptığımız sorgularda bilinen değerleri aradık. Örneğin fiyatı belirli bir değere aralığında olanlar, adı belirli olan bir ürünü aradık. Şimdi ise tam olarak bilinmeyen değerlere nasıl ulaşacağımızı öğreneceğiz. İçinde food geçen ürünlere ulaşmak istediğimizde, wildcard kullanmak durumundayız.
Bilgi: Arama kriteri (Search pattern), arama ifadeleri ve/veya wildcard karakterleri içeren sorgu metinidir.
SQL ifadelerinde wildcard kullanabilmek için LIKE anahtar sözcüğü gereklidir. WHERE deyimlerinden kullandığımız sorgulardan farklı olarak wildcard ifadelerine karşılık gelen değerlere ulaşırken, istediğimizden daha fazla kayıt karşımıza çıkabilir.
Daha önceden operatör olarak kullanılan karakterler, wildcard ifadesi olarak kullanıldığında tamamen farklı görevlerle yüklenirler.
Wildcard ifadeleri, yalnızca metin veri türü içeren alanların (yani kolonların) sorgularında kullanılabilir.
6.1.1 Yüzde (%) (perdent) Wildcard Karakteri
Wildcard karakterleri arasında en çok kullanılanı, yüzde karakteridir. Anlamı ise bir arama metninde herhangi bir karakterden herhangi bir sayıda bulunabileceğidir. Yani R harfi ile başlayan ürünlerin listesi istendiğinde LIKE anahtar sözcüğü ile % karakteri kombine edilecektir.
Örnek 6.1: R harfi ile başlayan ürünlerin listesini alalım.
Sorgu 23:
SELECT ProductName
FROM Products
WHERE ProductName LIKE 'R%'
Bu sorguda yüzde ifadesinden önce belirtilen karakter veya karakterler ile başlayan kayıtlara ulaşmak istedik. İkinci veya diğer herhangi bir karakter hakkında bir bilgi vermedik. Sonuç kümesi hakkında tek bildiğimiz, sadece ürün adlarının ilk harfinin R olacağıdır.
Önemli Not: Ms Access veri tabanı yönetim sistemi, % karakteri yerine * karakteri kullanır. Yani yukarıdaki sorgu Ms Access’de
SELECT ProductName
FROM Products
WHERE ProductName LIKE 'R*'
şeklinde olacaktır.
Bazı veri tabanı yönerim sistemlerinde büyük harf – küçük harf duyarlılığı vardır. O yüzden arama kriterini belirlerken buna dikkat etmek gerekebilir.
Yüzde karakteri ile bir metinin içinde geçen bir ifadeyi de arayabiliriz.
Örnek 6.2: İçinde Chef geçen ürün isimlerinin listesini alalım.
Sorgu 24:
SELECT ProductName
FROM Products
WHERE ProductName LIKE '%chef%'
Bu sorguda bulunmak istenen, içinde chef geçen ürünlerdir. O yüzden chef sözcüğünün başına ve sonuna birer yüzde karakteri konur ve ilgili kayıtlar listelenir.
Örnek 6.3: S ile başlayan ve s ile biten ürünleri listeleyelim.
Sorgu 25:
SELECT ProductName
FROM Products
WHERE ProductName LIKE 'S*s'
LIKE ‘S*s’ diyerek, sonuç kümem ilk harfi S, aradaki harflerle ve sayısıyla ilgili hiçbir kriter belirtilmesin, ve son harfi yine s olan kayıtları içersin demek istedik.
6.1.2 Alttire (_) (underscore) Wildcard Karakteri
Alttire karakterinin kullanımı da yüzde karakterine oldukça benzemektedir. Ancak yüzde karakterinden en önemli farkı, herhangi sayıda değil de, tek bir karaktere karşılık gelmesidir.
Önemli Not: Ms Access veri tabanı yönetim sisteminde _ yerine ? kullanılır.
Örnek 6.4: Ürün adı Tof ile başlayan ve 4 harften oluşan ürünleri listeleyelim.
Sorgu 26:
SELECT ProductName
FROM Products
WHERE ProductName LIKE 'Tof_'
Ürün adı Tof ile başlıyor ancak son, yani dördüncü karakteri neydi unuttum diyorsak alttire karakteri kullanmalıyız.
Eğer başında ve sonunda birer karakter olan ve arasında bir metin parçası içeren arama yapmak istiyorsak, wildcard ifademizin bir başına bir de sonuna birer alttire kullanacağız demektir.
Örnek 6.5: 5 harfli bir ürün adı var, ilk ve son harflerini bilmiyoruz ancak içinde “kur” sözcüğü geçiyor. Bu ürünün adı nedir?
Sorgu 27:
SELECT ProductName
FROM Products
WHERE ProductName LIKE '_kur_'
Örnek 6.6: Bir ürün var “Cha” ile başlıyor, 5 harfli ve adını hatırlayamadım.
Sorgu 28:
SELECT ProductName
FROM Products
WHERE ProductName LIKE 'Cha__'
Bu sorguda da, her bir karakter için bir alttireyi arama kriterinin içerisine yerleştirdik.
6.1.3 Köşeli Parantez ( [ ] )(brackets) Wildcard Karakteri
Köşeli parantez wildcard karakteri ile çeşitli karakterler bir küme halinde belirtilir. Bu karakter kümesinden herhangi biri eşleşebilir.
Bilgi: Köşeli parantez kullanımını her veri tabanı yönetim sistemi desteklemeyebilir. Access, SQL Server ve Sybase Adaptive Server veri tabanı yönetim sistemlerinin desteklediği bilinmektedir. Diğerleri için özelliklerini incelemenizi tavsiye ederiz.
Örnek 6.7: Müşteriler (Customers) tablosundan R veya T harfleriyle başlayan müşteri isimlerini bulalım.
Sorgu 29:
SELECT ContactName, CompanyName
FROM Customers
WHERE ContactName LIKE '[RT]*'
ORDER BY ContactName
Bu sorguda köşeli parantezler içerisinde belirtilen R ve T harflerinden biriyle başlayan müşteri isimleri görüntülenmiştir. Köşeli parantez içinde listelerken, IN operatöründeki gibi virgüller ile ayırmak sözkonusu değildir.
Bu küme istenildiği kadar genişletilebilir.
Bu sorgunun eşdeğeri sorgu 30’da belirtilmiştir.
Sorgu 30:
SELECT ContactName, CompanyName
FROM Customers
WHERE ContactName LIKE 'R*' OR ContactName LIKE 'T*'
ORDER BY ContactName
Gördüğünüz gibi OR operatörü kullanmak yerine köşeli parantezler ile sorgumuzu daha okunabilir kıldık.
Örnek 6.8: Adı R veya T ile başlamayan müşterilerimizi sorgulayalım.
Sorgu 31:
SELECT ContactName, CompanyName
FROM Customers
WHERE ContactName LIKE '[^RT]%'
ORDER BY ContactName
^ (karat karakteri) sayesinde bir kümenin değili elde edilir. Yani içinde R ve T olmayan elemanların oluşturduğu küme içerisinden değerler gelir.
Bilgi: Ms Access’de ise ^ operatörü yerine ! kullanılır. Yani sorgu 31’in Access’de çalışabilmesi için
SELECT ContactName, CompanyName
FROM Customers
WHERE ContactName LIKE '[!RT]*'
ORDER BY ContactName;
şeklinde kodlanması gerekir.
Karat karakteri (^) yerine NOT operatörünü de kullanabiliriz.
Sorgu 32:
SELECT ContactName, CompanyName
FROM Customers
WHERE NOT ContactName LIKE '[RT]%'
ORDER BY ContactName;
Karat karakteri kullandığımızda R ve T dışındaki elemanların oluşturduğu kümeyi elde ettiğimizi belirtmiştik. NOT operatörü ise aynı görevi yapar ve R ve T ile başlamayan tüm kayıtlara ulaştır.
Wildcard kullanmaya karar vermeden önce iki kere düşünün:
• Aynı işlevi bir operatör ile yapabiliyorsanız, bu sorgu performansını arttıracaktır. Çünkü wildcard ile arama yapmak, en yavaş çalışan görevdir.
• Wildcard karakterlerini kullanırken çok dikkatli olunuz. İstemeyerek yanlış sonuçlar elde edilebilir.
7 - TABLONUN ALANLARI İLE ÇALIŞMAK
Tablolarda bulunan kolonlar dışında, çeşitli hesaplamalar yapılarak yeni sonuçlar elde edilebilir.
7.1 Tabloların Alanları ile Neden Çalışılır?
Tablolar, bilgileri kolonlar halinde saklar. Ve bir veri tabanında çoğu bilgiler, küçük parçalara ayrıştırılarak saklanır. Ve kimi zaman bu kolonlardaki bilgilerin birleşitirilmesi gerekir. Belki de bu alanlar üzerinde çeşitli hesaplamaların da yapılması gerekebilir.
Örneğin;
• Bir müşterinin adı, soyadı ve bulunduğu şehri bir arada görüntülemek
• Adresi oluşturan kolonları birleştirerek tam adres oluşturmak
• Ürünleri ve isimlerini birlikte görüntülemek
vs.
Görüntülemek istediğimiz veriler, istenilen formatta değilse, onları biz istediğimiz şekilde görüntüleyebiliriz.
Bilgi: Tablonun kolonlarını kastederek, alan dediğimiz durumlar da olacaktır.
7.2 Alanların Birleştirilmesi
Alanlar ile yapacağımız ilk işlem, iki alanı bir kolonda birleştirmek olacaktır.
Örnek 7.1: Tedarikçiler (Suppliers) tablosundan tedarikçi adını ve bulunduğu ülkeyi bir arada bulunduracak sorguyu oluşturalım.
Sorgu 33:
SELECT CompanyName + ' (' + Country + ') '
FROM Suppliers
Burada tedarikçiler tablosundan tedarikçi şirketin adı ve bulunduğu ülkenin bilgisi + operatörü ile birleşitirilerek sonuca varılmıştır.
Yapılan işlemleri sıralayacak olursak;
• CompanyName kolonunda bulunan bilgi alınır
• Bir boşluk ve bir parantezden oluşan metin ifadesi eklenir.
• Sonra Country kolonunda bulunan bilgi de alınıp eklenir.
• Ve son olarak da bir parantez ve bir boşluk karakterleri de eklenir.
Bilgi: Ms Access, SQL Server ve Sybase veri tabanı yönetim sistemleri, metin ekleme işlemleri için + operatörünü desteklerler. DB2, Oracle, PostgreSQL ve Sybase ise metin ekleme işlemleri için || (pipe) operatörünü destekler.
MySql ise, metin ekleme işlemleri için bu iki operatörden hiçbirini desteklemez. Bu işlem için CONCAT() fonksiyonu tanımlanmıştır. MySql’de || operatörü OR operatörü ile aynı anlamdadır.
SELECT CONCAT(CompanyName, ‘( ‘, Country, ‘
’ )Bazı veri tabanı yönetim sistemlerinde alanlar birleştirilirken aralara istenmeyen boşluklar gelebilir. Bu durum, veri tabanı sistemlerinin kolonun maksimum karakter sayısına göre yerleştirmesinden kaynaklanır. İstenmeyen boşlukları kaldırmak için, RTRIM(), LTRIM() ve TRIM() SQL fonksiyonları kullanılabilir.
Sorgu 34:
SELECT RTRIM(CompanyName) + ' (' + RTRIM(Country) + ') '
FROM Suppliers
ORDER BY CompanyName
RTRIM sağdaki, LTRIM soldaki ve TRIM hem baştaki hem de sondaki boşlukları yok eder.
7.2.1 Kolon İsimlerinde Takma Ad Kullanımı (Alias)
Birleştirilen alanların oluşturduğu yeni kolona ait bir kolon ismi tanımlamak için AS anahtar sözcüğü kullanılır.
Örnek 7.2: Tedarikçiler (Suppliers) tablosundan tedarikçi adını ve bulunduğu ülkeyi bir arada bulunduracak sorguyu oluşturalım. Ve yeni oluşan kolona “Supplier_Name” adı verelim.
Sorgu 35:
SELECT RTRIM(CompanyName)+' ('+RTRIM(Country)+') '
AS Supplier_Name
FROM Suppliers
ORDER BY CompanyName
Sorguda da görüldüğü gibi, oluşturulan bu yeni kolona Supplier_Name adı verilmiştir. Dikkat ettiyseniz bir metin ifadesini ayırmak için kullanılan tek tırnakları burada kullanmadık.
7.2.2 Matematiksel İfadelerin Hesaplanması
Aslında alanlar üzerinde en çok yapılan işlemler matematiksel işlemlerdir. Sipariş detaylarına ilişkin verilerin tutulduğu “Order Details” tablosu üzerinde çeşitli işlemler yapılabilir.
Örnek 7.3: 10840 numaralı ürüne ait siparişlerin detaylarını görüntüleyelim.
Sorgu 36:
SELECT ProductID, Quantity, UnitPrice
FROM [Order Details]
WHERE OrderID = 10840
Bu sorgu sonucunda UnitPrice, her bir ürün için geçerli olan fiyatları gösterir. Peki ya bu siparişin toplam tutarını görüntülemek için ne yapılmalı?
Sorgu 37:
SELECT ProductID, Quantity,
UnitPrice, Quantity * UnitPrice AS Total_Price
FROM [Order Details]
WHERE OrderID = 10840
Sorgu sonucunda da görüldüğü gibi, mevcut kolonlardaki bilgiler kullanılarak yeni veriler elde edilmek isteniyorsa, SELECT deyiminin içerisinde bu işlemler tanımlanabilir. Bu alanlarda istenilen tüm matematiksel hesaplamalar yapılabilir.
8 - Veriler Üzerinde Değişiklik Yapan Fonksiyonlar
Veri tabanı yönetim sistemleri tarafından desteklenen SQL fonksiyonlarını öğreneceğiz.
8.1 - Fonksiyonlar Üzerine
SQL içerisinde dei programlama dillerinde olduğu gibi veriler üzerinde işlem yapmaya yarayan standart fonksiyonlar vardır.
Bir önceki konuda TRIM, LTRIM ve RTRIM fonksiyonlarından bahsetmiştik. Aslında fonksiyon kullanmak kimi zaman da işleri oldukça ağırlaştırmaktadır. Örneğin SELECT deyimi standart bir deyimken, fonksiyonlar standart değildir. Tablo 8.1’de veri tabanı yönetim sistemlerinin fonksiyonları arasındaki farklılıklar belirtilmiştir.
Fonksiyon Söz dizimi
Bir metnin bir kısmından yeni bir metin oluşturmak Ms Access MID(), DB2, Oracle ve PostgreSQL SUBSTR(), Ms SQL Server, MySQL ve Sybase ise SUBSTRING() fonksiyolarını kullanır.
Tür Dönüştürme DB2 ve PostgreSQL CAST(), MySQL, Sql Server ve Sybase CONVERT() fonksiyonlarını kullanır. Access ve Oracle her dönüşüm türüne göre bir fonksiyon kullanır.
Tarih Alma Access NOW(), DB2 ve PostgreSQL CURRENT_DATE, MySQL CURDATE(), Oracle SYSDATE, Sql Server ve Sybase GETDATE() fonksiyonlarını kullanır.
Tablo 8.1: Veri Tabanı Yönetim Sistemlerinde Bazı Fonksiyonlar ve Farklılıkları
Tablo 8.1’den de görüldüğü gibi, SQL fonksiyonları kullanmak o kadar da avantajlı değildir. Çünkü bir sistemde yazılmış kod, diğer bir sistemde çalışamayabilir. Yani taşınabilir değildir.
8.2 – Fonksiyon Kullanımı
Fonksiyonlar, yaptığı işlevlere göre gruplandırılabilir. Örneğin metin üzerinde işlemler yapan fonksiyonlar, nümerik işlem yapan fonksiyonlar, zaman ve tarih fonksiyonları ve sistem fonksiyonları olarak gruplandırılabilir.
8.2.1 Metinler Üzerinde İşlem Yapan Fonksiyonlar
Önceki bölümde gördüğümüz TRIM() fonksiyonları, bu gruba dahildir. Örneğin ele alınan metini tamamen küçük harfe dönüştüren LOWER() ve büyük harfe dönüştüren UPPER() fonksiyonları da bu gruptadır.
Örnek 8.1: Sorgu 33’deki sorgumuzun sonuçlarını tamamen büyük harflerle görüntüleyelim.
Sorgu 38:
SELECT UPPER(CompanyName) + ' (' + UPPER(Country) + ') '
FROM Suppliers
ORDER BY CompanyName
UPPER() fonksiyonu ile tüm karakterler büyük harfe dönüştürüldü. Tamamen küçük harfe dönüştürmek isteseydik LOWER() fonksiyonunu kullanacaktır. Sıklıkla kullanılan metinsel veriler üzerinde değişiklik yapan fonksiyonlar tablo 8.2’de gösterilmiştir.
Fonksiyon Açıklama
LEFT() Metinin sol tarafından karakter alır
RIGHT() Metinin sağ tarafından karakter adır
LENGHT(), Access’de LEN() Metinin uzunluğunu verir
LOWER(), Access’de LCASE() Metini tamamen küçük harflere dönüştürür
UPPER(), Access’de UCASE() Metini tamamen büyük harflere dönüştürür
LTRIM() Metinin solundaki boşlukları kaldırır
RTRIM() Metinin sağındaki boşlukları kaldırır
TRIM() Metinin başındaki ve sonundaki boşlukları kaldırır
SOUNDEX() Bir metinin SOUNDEX değerini geri döndürür
Tablo 8.2: Metin üzerinde değişiklik yapan Fonksiyonlar
Tablo 8.2’de belirtilen fonksiyonlardan SOUNDEX fonksiyonu, diğerlerinden çok farklı bür göreve sahiptir. SOUNDEX, bir metni, bu metinin fonetik karşılığını içeren alfanümerik başka bir metine dönüştüren bir algoritmadır. SQL ile doğrudan bir ilişkisi olmamasına rağmen pek çok veri tabanı yönetim sistemi bu algoritmayı destekler. Ms Access ve PostgreSQL desteklemez.
SOUNDEX kullanımına bir örnek verelim.
Örnek 8.2: Richter Supermarkt isimli müşterimizin “Michael Holz” adında bir kontağı olsun. Ya aslında bu kişinin adı “Michelle Holz” olduğu halde aynı şekilde söylendiğinden dolayı yanlış yazılmışsa?
Sorgu 39: değştirrr
SELECT CompanyName, ContactName
FROM Customers
WHERE ContactName = ‘Michelle Holz’
Bu sorgu elbette boş bir kümeyle geri dönecektir. SOUNDEX fonksiyonunu kullanırsak...
Sorgu 40:
SELECT CompanyName, ContactName
FROM Customers
WHERE SOUNDEX(ContactName) = SOUNDEX(‘Michelle Holz’

Örnekte de görüldüğü gibi hem ContactName alanı, hem de bu alanda arana değer SOUNDEX() fonksiyonu ile SOUNDEX değerine dönüştürülüp o şekilde arama yapılmış. Ve böylede ilgili kayıda ulaşılmıştır.
8.2.2 Tarih ve Zaman Üzerinde İşlem Yapan Fonksiyonlar
Her bir veri tabanı yönetim sisteminin kendine has tarih ve zaman bilgilerini saklama yöntemi vardır. Tabiki bizi ilgilendiren bu verilerin nasıl tutulacağı ve nasıl ulaşılacağıdır.
Tarih ve zaman bilgisini ayrıştıran çeşitli fonksiyonlar vardır.
Örnek 8.3: 1996 yılına ait tüm siparişleri listeleyelim.
Sorgu 41:
SELECT OrderID
FROM Orders
WHERE DATEPART(yy, OrderDate) = 1996
Bilgi: Ms Access’de DATEPART fonksiyonunun kullanımında bir farklılık vardır.
SELECT OrderID
FROM Orders
WHERE DATEPART('yyyy',OrderDate)=1996;
şeklinde belirtmek gerekir. Bu formu SQL Server ve Sybase de destekler. MySql ise
SELECT OrderID
FROM Orders
WHERE YEAR(OrderDate)=1996;
şeklide destekler. Oracle ise
SELECT OrderID
FROM Orders
WHERE to_number(to_char(OrderDate, ‘YY’
)=1996;şeklinde destekler.
Örnek 8.4: 1 Ocak 1996 ile 1 Ocak 1998 tarihleri arasındaki siparişleri listelemek isteyelim.
Sorgu 42:
SELECT OrderID, OrderDate
FROM Orders
WHERE OrderDate Between ‘1/1/1996’ And ‘1/1/1998’
Bilgi: Ms Access’de tarih belirtirken # işareti kullanılır.
WHERE OrderDate Between #1/1/1996# And #1/1/1998#
8.2.3 Nümerik İşlem Yapan Fonksiyonlar
Nümerik veriler üzerinde çeşitli cebirsel işlem yapan fonksiyonlardır. Metin ve tarih fonksiyonları kadar çok kullanılmazlar.
Tablo 8.3’de nümerik fonksiyonlar listelenmiştir.
Fonksiyon Açıklama
ABS() Sayının mutlak değerini verir
COS() Belirtilen açının trigonometrik kosinüs değerini verir
SIN() Belirtilen açının trigonometrik sinüs değerini verir
TAN() Belirtilen açının trigonometrik tanjant değerini verir
EXP() Belirtilen sayının exp üstel değerini verir
SQRT() Belirtilen sayının karekök değerini verir
PI() Pi sayısını verir
Tablo 8.3: Nümerik Fonksiyonlar
9 - Veriler Üzerinden Özet Bilgi Alınması
Tabloların kolonlarında saklanan verilere ilişkin özet bilgi elde edebilemek için SQL’in çeşitli toplam fonksiyonlarından (aggregate functions) yararlanacağız.
Bilgi: Aggregate Functions (toplam fonksiyonları), kolonlar üzerinde toplam değer, ortalama değer gibi bilgileri geri döndüren işlemleri yapan fonksiyonlardır.
9.1 Toplam Fonksiyonlarının Kullanımı
Tablolarda saklanan veriler üzerinde sıklıkla gerçekleşen işlemler için tasarlanmış fonksiyonların nasıl kullanıldığını inceleyelim.
Bir veri tabanından istenen bilgilerin başında;
• Bir tablodaki kayıt sayısını elde etmek
• Belirli bir koşulu sağlayan kayıtların sayısını elde etmek
• Tablonun kolonlarındaki verilerin toplamını elde etmek
• Kolonlara ait en yüksek, en düşük ve ortalama değerleri elde etmek
gelir. Bu gibi işlemler gerçekleştirmek için beş adet toplam fonksiyonu tasarlanmıştır. Tablo 9.1’de toplam fonksiyonları listelenmiştir.
Fonksiyon Açıklama
AVG() Kolona ait ortalama değer
COUNT() Kolondaki satır sayısı
MAX() Kolondaki en yüksek değer
MIN() Kolondaki en düşük değer
SUM() Kolondaki değerlerin toplamı
Tablo 9.1: Toplam Fonksiyonları (Aggregate Functions)
9.1.1 AVG() Fonksiyonu
Tablonun belirli bir kolonuna ait veriler üzerinde, o kolondaki tüm değerlerin toplanıp değer girilen satırların sayısına bölümünden elde edilen ortalama değeri geri döndürür. Yani değer girilmemiş satırlar işleme sokulmaz.
Örnek 9.1: Ortalama ürün fiyat bilgisini almak isteyelim.
Sorgu 43:
SELECT AVG(UnitPrice) AS Ortalama_Fiyat
FROM Products
Sorgudan da görüldüğü gibi, hesaplama yapılacak kolon ismi AVG() fonksiyonunun parantezleri içerisinde bildirildi. Ve hesaplanan bu değere Ortalama_Fiyat adında yeni bir kolon ismi verildi.
Örnek 9.2: Tedarikçi kayıt numarası 3 olan ürünlerin ortalama fiyat bilgisine ulaşmak isteyelim.
Sorgu 44:
SELECT AVG(UnitPrice) AS Ortalama_Fiyat
FROM Products
WHERE SupplierID = 3
Bu sorguda ise belirli bir kritere göre gelen sonuç kümesi üzerinde ortalama işlemi yapılmıştır.
AVG() fonksiyonu sadece nümerik değerler içeren kolon üzerinde işlem yapar ve bu kolon adı fonksiyon parametresinde belirtilmelidir. Ayrıca birden fazla kolona ait ortalama değeri elde etmek için elbette birden fazla AVG() fonksiyonu kullanılmalıdır.
Bilgi: NULL değer içeren satırlar, AVG() fonksiyonu tarafından işleme sokulmaz.
9.1.2 COUNT() Fonksiyonu
Adından da anlaşılacağı gibi COUNT() fonksiyonu, belirli bir kolondaki kayıtları sayar. Bu fonksiyonun iki farklı kullanım şekli vardır.
• COUNT(*) ile, tablodaki kayıt sayısı elde edilir. NULL değerler de sayılır.
• COUNT (kolon_adı) ile, NULL değer içeren satırlar işlem dışı tutularak belirli bir kolondaki kayıt sayısı elde edilir.
Örnek 9.3: Kaç tane müşterimiz var acaba?
Sorgu 45:
SELECT COUNT(*) AS Müşteri_Sayısı
FROM Customers
COUNT(*) kullanılan sorgularda satır içerisinde veri girilip girilmediğine bakılmadan toplam satır sayısı geri döndürülür.
Örnek 9.4: Fax numarası girilmiş kaç tane müşterimiz var acaba?
Sorgu 46:
SELECT COUNT(Fax) AS Faxlı_Müşteri_Sayısı
FROM Customers
COUNT(kolon_adı) kullanılan sorgularda kolona ait veriler girilmişse sayım yapılır. Yani NULL değer içeren kayıtlar sayılmaz.
9.1.3 MAX() Fonksiyonu
MAX() fonksiyonu, belirtilen kolondaki en büyük değere ait veriyi geri döndürür.
Örnek 9.5: En yüksek fiyatlı ürünü öğrenmek isteyelim.
Sorgu 47:
SELECT MAX(UnitPrice) AS Maksimum_Fiyat
FROM Products
Bu örnekte en pahalı ürün görüntülenmiştir.
MAX() fonksiyonu nümerik değerlerin yanı sıra, zaman, tarih ve metinsel ifadelerde de kullanılır. Çoğu veri tabanı yönetim sistemi bunu destekler. Örneğin metinsel ifadeler içeren bir kolona MAX() fonksiyonu uygulanırsa alfabedeki sıralamaya göre en son sıraya düşen kayıt görüntülenir.
Örnek 9.6: Alfabetik listeye göre en sonda yer alan müşteriyi görüntüleyelim.
Sorgu 48:
SELECT MAX(CompanyName) AS En_Sondaki_Müşteri
FROM Customers
MAX() fonksiyonu NULL değer içeren kayıtlar ile işlem yapmaz.
9.1.4 MIN() Fonksiyonu
MIN() fonksiyonu, belirtilen kolondaki en küçük değere ait veriyi geri döndürür.
Örnek 9.7: En düşük fiyatlı ürünü öğrenmek isteyelim.
Sorgu 49:
SELECT MIN(UnitPrice) AS Minimum_Fiyat
FROM Products
Bu örnekte en ucuz ürün görüntülenmiştir.
MIN() fonksiyonu nümerik değerlerin yanı sıra, zaman, tarih ve metinsel ifadelerde de kullanılır. Çoğu veri tabanı yönetim sistemi bunu destekler. Örneğin metinsel ifadeler içeren bir kolona MIN() fonksiyonu uygulanırsa alfabedeki sıralamaya göre en öndeki kayıt görüntülenir.
9.1.5 SUM() Fonksiyonu
SUM() fonksiyonu, belirtilen kolondaki değerlerin toplamını geri döndürür.
Örnek 9.10: Toplam kaç adet malın sipariş verildiğini bulalım.
Sorgu 50:
SELECT SUM(Quantity) AS Toplam_Ürün
FROM [Order Details]
Bu örnekte Order Details tablosu baştan sona dolaşılmış ve Quantity kolondaki tüm değerler toplanmıştır.
Örnek 9.11: 10255 numaralı siparişte toplam kaç adet malın sipariş verildiğini bulalım.
Sorgu 51:
SELECT SUM(Quantity) AS Toplam_Ürün
FROM [Order Details]
WHERE OrderID = 10255
Bu örnekte ise 10255 numaralı siparişe ait kayıtlardaki Quantity kolonuna ait değerler toplanmıştır.
Örnek 9.12: 10255 numaralı siparişten elde edilecek tutarı bulalım.
Sorgu 52:
SELECT SUM(Quantity * UnitPrice) AS Tutar
FROM [Order Details]
WHERE OrderID = 10255
Sorgudan da görüldüğü gibi, önce Quantity ile UnitPrice verileri çarpılarak her bir siparişin tutarı hesaplandı. Ve bu alan SUM() fonksiyonu ile toplam tutar elde edildi.
Toplam fonksiyonları sayesinde farklı kolonlara ait matematiksel işlemler gerçekleştirilebilir.
NULL değer içeren kayıtlar da SUM() fonksiyonu tarafından işleme sokulmazlar.
9.2 - Farklı Değerler Üzerinde Toplam İşlemleri
Toplam fonksiyonları ile yaptığımız işlemler tüm kayıtlar üzerinde gerçekleştirildi. ALL anahtar sözcüğü kullanılmasa da, aslında toplam fonksiyonlar içerisinde varsayılan değer olarak ALL anahtar sözcüğünün kullanılmıştır. DISTINCT anahtar sözcüğü ise, aynı değere ait kayıtlardan sadece birer tanesinin işleme koyulacağını belirtir.
Bilgi: ALL değeri, varsayılan değerdir. Yani toplam fonksiyonlarında hiçbir değer belirtilmezse, ALL değeri kullanılmış kabul edilir.
Ancak, MS Access veri tabanı yönetim sistemi, toplam fonksiyonlarında DISTINCT anahtar sözcüğünü desteklemez.
Örnek 9.13: 15 kayıt numaralı tedarikçiye ait ürünlerin tekil değerilerinin ortalama fiyatını almak isteyelim.
Sorgu 53:
SELECT AVG(DISTINCT UnitPrice) AS tekil_ortalama_deger
FROM Products WHERE SupplierID = 15
Burada her bir fiyat değeri sadece bir kere işleme sokulmuştur. Yani aynı fiyattaki ürünler sadece bir kez toplanır. Ve tabiki ortalama değer bu şekilde hesaplanır.
kaç farklı ülke ile çalıışıldı ekle
DISTINCT anahtar sözcüğü COUNT(*) fonksiyonu ile kullanılamaz. Ancak kolon adı belirtilerek COUNT(kolon_adı) şeklinde kullanılabilir.
9.3 - Toplam Fonksiyonlarının Beraber Kullanımı
Toplam fonksiyonları ile yaptığımız örnekler bunların birer birer kullanılmasıyla ilgiliydi. Şimdi ise aynı ifadede birden fazla toplam fonksiyonunun nasıl kullanıldığına bakacağız.
Örnek 9.14: Ürünler tablosunda, ürün sayısını, en düşük, en yüksek fiyatı ve ortalama değeri gösterelim.
Sorgu 54:
SELECT
COUNT(*) AS Ürün_Sayısı,
MIN(UnitPrice) AS En_Düşük,
MAX(UnitPrice) AS En_Yüksek,
AVG(UnitPrice) AS Ortalama_Deger
FROM Products
Sorgudan da görüldüğü gibi ürün fiyatlarına ilişkin kolona dört adet toplam fonksiyonu uygulanmıştır.
10 - Verilerin Gruplandırılması
Tablolara ait içerikler üzerinde verileri nasıl gruplandırılacağını göreceğiz. Bu durumda SELECT deyiminin yanında, GROUP BY ve HAVING deyimlerini kullanacağız.
10.1 - Veri Gruplama Nedir?
SQL toplam fonksiyonları sayesinde verilere ait çeşitli özet bilgileri elde etmeyi öğrendik. Bu sorgular belirli bir değere ilişkin verileri içermişti. Şimdi ise verileri belirli bir kritere göre gruplayarak toplam fonksiyonlarını nasıl kullanacağımızı öğreneceğiz.
Örnek 10.1: 4 kayıt numaralı tedarikçiye ait ürünlerin sayısını öğrenelim.
Sorgu 55:
SELECT COUNT(*) AS Ürün_Sayısı
FROM Products
WHERE SupplierID = 4
Bu örnekte 4 numaralı tedakçiden gelen ürünlerin sayısını aldık. Peki her bir tedarikçiden gelen ürünlerin sayısını ayrı ayrı olarak öğrenmek istesek ne yapacağız?
10.2 - Grup Oluşturmak
Gruplar, SELECT ifadesi ile GROUP BY deyiminin birleşmesiyle oluşur.
Örnek 10.2: Her bir tedarikçiden gelen ürünlerin sayısını ayrı ayrı görüntülemek isteyelim.
Sorgu 56:
SELECT SupplierID, COUNT(*) AS Ürün_Sayısı
FROM Products
GROUP BY SupplierID
Bu sorgunun sonucunda, her bir tedarikçi ve bu tedarikçilere ait ürün sayısı bilgisi listelenmiştir. GROUP BY deyimi ile belirtilen kolon adına göre kayıtlar ayrıştırılır, sonra SELECT ifadesinde belirtilen COUNT(*) fonksiyonu, sayımı yapar ve görüntüler.
Yani kayıtlar, GROUP BY ile belirtilen kolon sayısındaki farklı veriler kadar sayıda satır oluşacak ve her bir kayıtta kaç adet ürün bulunduğu da hemen yanındaki kolonda görüntülenecektir.
GROUP BY deyimini kullanmadan önce, şu bilgileri göz önünde bulundurmalıyız:
• İstenildiği kadar sayıda GROUP BY deyimi iç içe kullanılabilir.
• GROUP BY deyimi kullanıldığında, toplam fonksiyonu SELECT ifadesinin en son alanında bildirilmelidir.
• GROUP BY deyiminde belirtilen ifade, ya geçerli bir kolon adı olmalıdır, ya da toplam fonksiyonları dışında geçerli bir ifade olması gerekir.
• GROUP BY deyiminin nümerik değer içeren kolonlara uygulanması gereklidir.
• Gruplandırılacak kolonda NULL değer varsa, NULL değeri de bir grup değeri olarak ayrılır. Birden fazla NULL değeri içeren kayıt varsa, hepsi bir grupta toparlanır.
• GROUP BY deyimi WHERE anahtar sözcüğünden sonra ve ORDER BY deyiminden önce gelmelidir.
10.3 - Grup Üzerinde Filtreleme Yapmak
GROUP BY ile veri gruplarken hangi verilerin gruba katılacağı veya ayrı tutulacağı da belirtilebilir. Örneğin, toplam sipariş miktarı 1200 adetten fazla olan ürün kodlarının görüntülenmesini isteyelim. O zaman her bir kayıtlar üzerinde tek tek değil, gruplar üzerinde filtreleme yapılacaktır.
WHERE deyimini biliyoruz. Ancak bu durumda WHERE deyimi işe yaramayacaktır. Çünkü WHERE deyimi kayıtlat üzerinde filtreleme yapabilirken, gruplar üzerinde filtreleme yapamayacaktır. Peki WHERE deyiminin yerini tutacak olan şey nedir? HAVING yan cümlesidir. WHERE deyimi ile kullandığımız tüm işlemleri HAVING yan cümlesi ile de kullanabileceğiz.
Örnek 10.3: Toplam sipariş miktarı 1200 adetten fazla olan ürün kodları listelenmiştir.
Sorgu 57:
SELECT ProductID, SUM(Quantity) AS total_quantity
FROM [Order Details]
GROUP BY ProductID
HAVING SUM(Quantity) > 1200
Sorguda da görüldüğü gibi, SELECT ifadesinde kullanılan ProductID ve Quantity alanları, GROUP BY ve HAVING deyimleri ile de birleştirilmiştir. Sorguyu sondan başa doğru okursak, sipariş miktarı 1200’den fazla olan ürünleri al, ProductID değerine göre grupla gibi bir cümle çıkar.
Örnek 10.4: 100’den fazla müşteriden sipariş alan çalışanları, müşteri sayısına göre gruplayarak listeleyelim.
Sorgu 58:
SELECT EmployeeID, COUNT(CustomerID) AS Müşteri_Sayısı
FROM Orders
GROUP BY EmployeeID
HAVING COUNT(CustomerID)>100
ORDER BY EmployeeID
Sorguda da görüldüğü gibi, SELECT ifadesinde kullanılan EmployeeID ve CustomerID alanları, GROUP BY ve HAVING deyimleri ile de birleştirilmiştir.
Örnek 10.5: Onaltı veya daha fazla sipariş veren müşterileri listeleyelim.
Sorgu 59:
SELECT CustomerID, COUNT(*) AS Siparişler
FROM Orders
GROUP BY CustomerID
HAVING COUNT(*) >= 16
Örneklerden de görüldüğü gibi, WHERE ve HAVING anahtar sözcükleri arasındaki en büyük fark; WHERE deyimi veri gruplandırılmadan önce filtreleme yapar, HAVING ise veriyi gruplandırdıktan sonra filtreleme yapar.
WHERE ve HAVING deyimlerinin birlikte kullanıldığı durumlar da olacaktır.
Örnek 10.6: 15 lira ve daha yukarı fiyata sahip ürünleri tedarikçilerine göre gruplandırarak listeleyelim.
Sorgu 60:
SELECT SupplierID, COUNT(*) AS Ürün_Sayısı
FROM Products
WHERE UnitPrice >= 15
GROUP BY SupplierID
HAVING COUNT(*) >=1
10.4 SELECT İfadesinin İşlem Sırası
Öğrendiğimiz deyimlerin bir arada kullanılmasına ilişkin bir tablo tanımlayalım.
Deyim Açıklama Gereklilik
SELECT Geri döndürelecek kolon veya ifadeler Evet
FROM Veri alınacak tablo Sadece tablodan veri seçimi yapılacağı durumlarda gerekli
WHERE Filtreleme Hayır
GROUP BY Grup tanımalam Gruplar ile toplam fonksiyonlarının kullanıldığı durumda
HAVING Grup filtrelemesinde Hayır
ORDER BY Sıralanarak görüntüleme Hayır
Tablo 10.1: Deyimlerin Kullanım Sırası
11 - Alt Sorgular
Bu bölümde alt sorgular ile çalışacağız.
11.1 Alt Sorgu Nedir?
Bu zamana kadar çalıştığımız örnekler sadece bir sorgu üzerinde gelen verileri içeriyordu.
Bilgi: Sorgu, herhangi bir SQL ifadesine denir.
Alt sorgu ise, bir sorgu içinda başka bir sorgunun yer alması durumudur. Alt sorgulara neden ihtiyaç duyulduğu ileriki örneklerde göreceğiz.
Bilgi: MySQL kullanıcıları, 4.1’den önceki versiyonlar alt sorguları desteklemez.
11.2 Alt Sorgular ile Filtreleme
Kullandığımız Northwind veritabanı, tabloları arasında ilişkiler kurulmuş bir veri tabanıdır. Siparişlere ait bilgiler iki tabloda saklanmıştır. Orders, siparişi veren müşteriye ve zamana ait bilgileri tutar. Order Details tablosu ise bu sipariş içindeki ürünleri, adedini, fiyat ve indirim bilgilerini tutar. Müşterilere ilişkin veriler ise Customers tablosunda tutuldu, Order ve Order Details tablolarında müşteriye ait kimlik numarasına referans verildi.
Örneğin 37 numaralı ürünü sipariş veren tüm müşterileri listelemek için neler yapılmalıdır?
1 – 37 numaralı ürünü içeren tüm siparişleri getir.
2 – Bir önceki adım sonucu gelen kümenin içerisinden müşteri kimlik numaraları alınır.
3 – Her bir müşterinin bilgisini bu şekilde al.
Bu olayları gerçekleşitirmek için 2 ayrı sorgu tasarlayabiliriz.
Örnek 11.1: 37 numaralı ürüne ait siparişlerin sipariş numaralarını getirelim.
Sorgu 61:
SELECT OrderID FROM [Order Details]
WHERE ProductID = 37
Şimdi ise 61 numaralı sorgunun sonuç kümesindeki her bir eleman için müşteri kimlik numaralarını almamız gerekir. Bu sorgunun sonuç kümesi, 10259, 10337, 10408, 10523, 10847, 10966 den oluşur.
Örnek 11.2: 61 numaralı sorgunun sonuç kümesindeki müşterilerin kimlik numaralarını alalım.
Sorgu 62:
SELECT CustomerID FROM Orders
WHERE OrderID IN(10259, 10337, 10408, 10523, 10847, 10966)
Peki bu iki ayrı sorguyu birlikte kullanarak daha verimli bir sorgu oluşturmak için ne yapmalıyız?
Örnek 11.3: 37 numaralı ürünü sipariş veren tüm müşterileri listelemek isteyelim.
Sorgu 63:
SELECT CustomerID
FROM Orders
WHERE OrderID
IN ( SELECT OrderID FROM [Order Details] WHERE ProductID = 37)
Bu sorguda ilk önce içeride bildirdiğimiz sorgu çalıştırılacak, bu sorgudan oluşan sonuç kümesi içerisindeki bilgiler ise diğer sorguya veri olarak aktarılır. Yani önce
“SELECT OrderID FROM [Order Details] WHERE ProductID = 37”
sorgusu çalıştırılır. Bu sorgu sonucunda (10259, 10337, 10408, 10523, 10847, 10966) verileri gelir. Daha sonra ise bu siparişleri veren müşteri numaralarına erişmek için
“SELECT CustomerID FROM Orders
WHERE OrderID IN ( içteki sorgu sonucu)”
sorgusu çalıştırılır.
İşleme her zaman en içteki sorgudan başlanır.
Bu sorgular sonucunda müşteri numaralarını elde ettik. Müşteri numarasına göre ayrıntılı bilgi almak için ise Örnek 11.4’e bakalım.
Örnek 11.4: 37 numaralı ürünü sipariş veren her bir müşterinin adını ve kontak ismini alalım.
Sorgu 64:
SELECT CompanyName, ContactName
FROM Customers
WHERE CustomerID IN
(SELECT CustomerID FROM Orders WHERE OrderID IN
(SELECT OrderID FROM [Order Details]
WHERE productID = 37))
Bu sorguda iç içe iki sorgu ile sonuca ulaşılmıştır. Gördüğünüz gibi önce 37 numaralı ürüne ait sipariş numaraları, sonra bu numaralı siparişleri veren müşterilerin kayıt numaraları, ve en sonunda ise bu numaralara sahip müşterilerin iletişim bilgileri alınır.
11.3 Alt Sorguları Hesaplanmış Alanlar Olarak Kullanmak
Alt sorguları kullanmanın bir diğer yolu ise, hesaplanmış alanlar içinde alt sorgulara yer vermektir. Örneğin, Customers tablosunda her bir müşterinin verdiği toplam sipariş miktarını görüntülemek isteyelim. Biliyoruz ki siparişlerin hepsi Orders tablosunda tutulur ve OrderID anahtar değeri ile ulaşılır.
Örnek 11.5: Her bir müşteri tarafından verilen sipariş miktarını görüntüleyen sorgu oluşturalım.
Bu işlemi gerçekleştirmek için şu adımları gerçekleştirmeliyiz:
1- Customers tablosundan müşterilerin listesi gelir
2- Her bir müşteri için, Orders tablosunda verilen siparişler hesaplanır
Biliyoruz ki bir tablodaki kayıtları saymak için SELECT COUNT(*) deyimi kullanılır, WHERE yan cümlesi ile her bir müşteri numarası için sipariş bilgilerini ulaşılır. Örneğin kodu ‘CACTU’ olan müşteriye ait siparişleri listelemek için
Sorgu 65:
SELECT COUNT(*) AS Toplam_Siparis
FROM Orders
WHERE CustomerID = 'CACTU'
sorgusu kullanılır. Ancak görüyoruz ki bu sorgu sadece CACTU kodlu müşteriye ait siparişleri listeler. Biz bu sorguyu her bir müşteri için elde etmek istesek ne yapmamız gerekir? İşte burada işimiz biraz daha karmaşıklaşacak. SELECT COUNT(*) sorgusunu alt sorgu olarak kullanmamız gerekecek.
Sorgu 66:
SELECT CompanyName, Country,
(SELECT COUNT(*) FROM ORDERS
WHERE Orders.CustomerID = Customers.CustomerID)
AS Toplam_Siparisler
FROM Customers
ORDER BY CompanyName
Daha önce kullanmadığımız bir biçimde sorgu kalıbı kullandık.
Olayı şöyle canlandıralım:
CompanyName, Country alalarının yanında bir de bu şirketlerden gelen toplam sipariş sayısını öğrenmek istiyoruz. Bu kolonu oluşturmak için bir iç sorgu yapıyoruz.
(SELECT COUNT(*) FROM Orders
WHERE Orders.CustomerID = Customers.CustomerID
AS Toplam_Siparisler)
İşte bu sorgu, her bir şirket için verilen sipariş sayısını hesaplar. Peki nasıl? Dikkat ettiyseniz WHERE yan cümlesinden sonra Orders ve Customers tablolarının CustomerID alanları birbirlerine bağlanmış, yani ilişkilendirilmiş. Eğer burada
Orders.CustomerID = Customers.CustomerID
ifadesi kullanılmasaydı bu işlem gerçekleşmezdi.
12 – Tabloları Birleştirme
Bu bölümde tabloları birleştirerek yep yeni sorgular oluşturacağız.
12.1 Tablolar Arası Veri Birleştirme Nedir?
SQL’in en güzel ve en güçlü yönlerinden biri, sorguların çalıştırıldığı zaman birden fazla tabloya ait verilerin bir sonuç kümesi içinde görüntülenebilmesidir. Burada pek çok şeye dikkat etmemiz gerekecek. Hangi tablonun tekil anahtar değeri (primary key) ile hangi tablonun foreign key değerlerinin birleştirilmesi gerektiği bilgileri iyice belirlenmelidir.
Aslında verinin nasıl birleştirileceğinden önce ilişkisel tablolar üzerinde biraz bilgi tazelemesi yapmak gerekiyor.
Örneğin veri tabanımızda ürün kataloğu içeren bir veri tablomuz var. Her bir katalog ürünü ise kendi sırasında yer almakta. Her bir ürüne ait tanımlama, fiyat, tedarikçi bilgisi gibi verileri de bulundurmamız gerekir.
Peki, aynı tedarikçiye ait ürünlerimiz varsa ne olacak? Tedarikçi bilgilerini nerede tutacağız? Tabiki her bir ürün için tek tek bu bilgileri girmemiz gereksiz olacak.
İşte bu gibi durumlarda veriler, parçalanabilecek en küçük parçalara ayrıştırılacak, tablolara bölüştürülecek, ve bu tablolar birbirleriyle ilişkilendirilecektir.
Bu örneğimizde Products, Suppliers tablolarını ele alırsak, her bir tedarikçiye bir tekil kimlik numarası (ID) verilecek ve Products tablosunda ise her bir ürünün tedarikçi alanına ise tedarikçi adı değil, kimlik numarası girilecektir.
12.2 Tablolar Arası Veri Nasıl Birleştirilir (Join)?
Aslında join işlemi oldukça basittir. Veri getirilecek tüm tabloların isimleri ve bu tabloların hangi alanlar vasıtasıyla birleştirileceği bilgisi belirtilmelidir.
Örnek 12.1: Ürünlerimize ait tedarikçi firma adı, ürün adı ve fiyatını görüntüleyelim.
Sorgu 67:
SELECT CompanyName, ProductName, UnitPrice
FROM Suppliers, Products
WHERE Suppliers.SupplierID = Products.SupplierID
Sonuç kümesini incelersek, Suppliers tablosundan CompanyName, ve Products tablosundan ProductName, UnitPrice alanlarının getirildiğini görürüz. Burada en önemli olay, bu iki tablonun SupplierID alanları ile birleştirilebiliyor olmasıdır. Suppliers tablosundaki SupplierID tekil anahtar (primary key) ve Products tablosundaki SupplierID ise foreign key vazifesindedir.
SELECT anahtar sözcüğü ve WHERE yan cümlesini iki farklı tablodan veri alıp birleştirmek için kullandık. İlişkili tablolardan veri almak için gerekli olan, WHERE yan cümlesinden sonra bu tablolar arasında ilişki kuracak alanın belirtilmesidir.
Aslında bu sorguyu şu şekilde yeniden yazarsak, aynı kolon adına sahip olabilecek tablolarda sorun çıkmasını engelleriz.
Sorgu 68:
SELECT Suppliers.CompanyName,
Products.ProductName, Products.UnitPrice
FROM Suppliers, Products
WHERE Suppliers.SupplierID = Products.SupplierID
12.3 WHERE Yan Cümlesinin Önemi
İki tablo arasındaki ilişkiyi belirtmek için WHERE yan cümlesini kullanıyor olmamız ilk başta biraz tuhaf gelebilir. SELECT ifadesinde belirtilen ilişkiler, sorgu çalıştığı zaman kurulur ve görüntülenir.
WHERE yan cümlesinden sonra belirtilen tablolar arası ilişki ifadesi, unutulursa istenilenden fazla sayıda sonuç görüntüler.
Sorgu 69:
SELECT CompanyName, ProductName, UnitPrice
FROM Suppliers, Products
Bu sonuç kümesi oldukça kalabalık değil mi? Sebebi ise, Suppliers tablosundaki kayıtlar ile Products tablosundaki kayıtların kartezyen çarpılmasıdır. Yani Suppliers tablosundaki bir kayıt, Products tablosundaki tüm kayıtlarla birer birer eşleşir. Yani sonuç kümesindeki eleman sayısı (Suppliers tablosundaki kayıt sayısı) * (Products tablosundaki kayıt sayısı) na eşittir.
İşte bu gereksiz eşleşmeleri önlemek için WHERE yan cümlesinden sonra Suppliers.SupplierID = Products.SupplierID ifadesi kullanılır. Tekrar belirtmeliyiz ki, iki tablo arasındaki ilişkiyi belirtmek için tekil anahtar olan değeri tablo adı ile birleştirip, foreign key olarak kullanılacak alanı bu tablo adı ile birleştiririz.
12.4 INNER JOIN
Bir önceki konuda iki tablo arasında kurduğumuz birleştirme ilişkisine “equijoin” denir. Yani iki tablo arasında eşitliğin test edilmesi ile oluşturulan join.
Şimdi biraz daha farklı bir sentaks kullanacağız.
Örnek 12.2: Ürünlerimize ait tedarikçi firma adı, ürün adı ve fiyatını görüntüleyelim.
Sorgu 70:
SELECT CompanyName, ProductName, UnitPrice
FROM Suppliers INNER JOIN Products
ON Suppliers.SupplierID = Products.SupplierID
İşte tablolar arasındaki ilişkiler için INNER JOIN anahtar sözcüğünü kullanmamız daha yararlı olacaktır.
Sorguyu incelersek, hangi tablodan hangi tabloya ilişki kurulacağı FROM anahtar sözcüğünden sonra belirtilir.
Hatırlayacağınız gibi Suppliers tablosunda her bir tedarikçiye verilen numaralar SupplierID alanında tutuluyordu (primary key). Products tablosunda ise ürünün hangi tedarikçiye ait olduğu bilgisi yine SupplierID alanında tutuluyordu (foreign key).
Bu iki alan arasında ON anahtar sözcüğü kullanılır.
INNER JOIN Products ON Suppliers.SupplierID = Products.SupplierID
Burada kullanılan INNER JOIN ve ON anahtar sözcükleri, daha önce kullandığımız WHERE
Suppliers.SupplierID = Products.SupplierID ile oluşturulan ilişki yerine kullanılır.İlişkinin yönü belirtildiği için bu tarz kullanım önerilmektedir.
İki tablo arasında ilişki kurmak için WHERE geçerli olsa da, çoklu tablolarda o kadar da kolay olmayacaktır.
12.5 Çoklu Tabloları JOIN ile Birleştirmek
SELECT ifadesi içerisinde istenildiği kadar tablo arasında ilişki kurulabilir. SQL bunun için bir sınır belirlememiştir. Olay aslında o kadar da karmaşık değildir. Yapılması gereken, öncelikle tüm tablolar listelenir ve sonra birbirleri arasındaki ilişki tanımlanır.
Örnek 12.3: 10274 numaralı siparişe ait ayrıntılı bilgi almak istiyoruz.
Sorgu 71:
SELECT Products.ProductName, Suppliers.CompanyName,
[Order Details].UnitPrice,[Order Details].Quantity
FROM [Order Details], Products, Suppliers
WHERE Products.SupplierID = Suppliers.SupplierID
AND
[Order Details].ProductID = Products.ProductID
AND OrderID = 10274
Unutmayalım ki sorguyu incelemek istiyorsak, cümleyi okumaya en sondan başlamalıyız. Bu sorguda, Order Details tablosundan 10274 numaralı sipariş ele alınır. Bu kayıt üzerinden UnitPrice ve Quantity bilgisinin yanında Products tablosuna ulaşılır ve ProductName bilgisi alınır. Aynı şekilde Suppliers tablosundan CompanyName bilgisi alınır.
Aslında bu sorgu, alt sorgular kullanılarak da çalıştırılabilirdi.
Örnek 12.4: 9 numaralı ürünü sipariş veren müşterilere ait ayrıntılı bilgi almak istiyoruz.
Sorgu 72:
SELECT CompanyName, ContactName FROM Customers
WHERE CustomerID IN
(SELECT CustomerID FROM Orders WHERE OrderID IN
(SELECT OrderID FROM [Order Details]
WHERE ProductID = 9))
Sonuca ulaşmak için hangi yolun kullanılacağı tamamen sizin deneyimlerinize dayanmaktadır. Önemli olan doğru veriye ulaşmak. Sorgu 73 bu sonucu farklı yöntemle görüntüler.
Sorgu 73:
SELECT CompanyName, ContactName
FROM Customers, Orders, [Order Details]
WHERE Customers.CustomerID = Orders.CustomerID
AND [Order Details].OrderID = Orders.OrderID
AND ProductID = 9
13 – İleri Seviyede Tabloları Birleştirme
Bu bölümde tabloları birleştirme işleminde daha ileri seviyede işlemler nasıl yapılır inceleyeceğiz. Toplam fonksiyonlarını joinler içinde nasıl kullanılacağını da göreceğiz.
13.1 Tablolara Yeni Adlar Vermek (Using Aliases)
Önceki bölümlerde hesaplanan alanlara yeni isimler verildiğini öğrenmiştik.
SELECT CompanyName + ‘ (‘ + Country + ‘
’ AS Supplier_TitleFROM Suppliers ORDER BY CompanyName
Alanlara yeni isimler vermenin yanı sıra, tablolara da yeni isimler verebiliriz. Tablolara yeni isim verme ihtiyacı neden duyulur?
• SQL sentaksını kısaltmak
• Tek bir SELECT ifadesinde aynı tabloyu birden fazla kez kullanmak
Örnek 13.1: 9 numaralı ürünü sipariş veren müşterilere ait ayrıntılı bilgileri alalım.
Sorgu 74:
SELECT CompanyName, ContactName
FROM Customers AS C, Orders AS O, [Order Details] AS OD
WHERE C.CustomerID = O.CustomerID
AND OD.OrderID = O.OrderID
AND ProductID = 9
Sorgudan da görüldüğü gibi 3 tablodan veri alıp birleştirildi. C dediğimiz şey aslında Customers tablosunun yerini tuttu. C.CustomerID ise, Customers.CustomerID ile eşittir.
Bilgi: Oracle, AS anahtar sözcüğünü desteklemez. Customers AS C yerine, Customer C kullanılır.
Alan adlarında kullanılan yeni isimler görüntülenir, ancak tablolarda böyle bir durum yoktur. Yani kullanıcı bu isimleri görmez.
13.2 Farklı JOIN Türlerinin Kullanımı
INNER JOIN ve equijoin kavramlarını gördük. Şimdi ise üç farklı join türü inceleyeceğiz.
13.2.1 Self Join (Kendisiyle İlişkilendirmek)
Tablolara yeniden isim vermek hakkında bahsettiğimiz gibi, aynı sorgu içinde aynı tablo adını birden fazla kullanmamızın gerektiği durumlar olacaktır.
alıntıdır

rep içinde teşekkürler