SQL çalışmalarımız tüm hızıyla sürüyor :) Yazılar biraz uzun oluyor ama bunun sebebi uygulamalı olarak deyimleri incelememiz. Eğer siz de bu deyimleri uygulayarak yapıyorsanız sonuçlarınızı karşılaştırabilmeniz adına sorguların çıktılarını da veriyorum.
Şimdi bugün de alt sorguları işleyeceğiz. Hemen kısaca giriş yapalım. Diyelim ki yöneticiniz sizden X kişisinin çalıştığı ülkede çalışan kişilerin maaşlarını görüntüleyen bir rapor istedi. Bu durumda tek bir sorgu ile işin içinden çıkmanız gerçekten zor. İç içe iki sorgu ile çalışmak durumundasınız. Bu gibi durumlarda sorgular hiyerarşik olarak dizilmelidir. Yani içteki sorgudan dönen sonucu dıştaki sorgu işleyerek asıl amaca dair çıktıyı size vermelidir. Mesela verdiğimiz örnekte içteki sorgu X kişisinin çalıştığı ülkeyi çekmelidir. Ana sorgu ise bu şehirde çalışan kişilerin maaşlarını görüntüler.
Alt sorguların amacını açıkladıktan sonra konuya başlayabiliriz.
Alt Sorgu ve Özellikleri
Alt sorguların söz dizimi genelde şu biçimdedir:
SELECT liste
FROM tabloismi
WHERE karsilastirmaoperatoru
(SELECT liste
FROM tabloismi);
Bu tip sorgularda öncelikle içteki alt sorgu çalışır. Buradan dönen sonuçlar ana sorgu icra edilir. Yazım tarzına bakılırsa parantez () kullanılarak alt sorgu yazılmalıdır. Ayrıca ana sorgudan ayrıldığını belirtmek ve okunabilirliği artırmak amacıyla alt sorguyu sağdan girintili olacak biçimde vermeniz sorgunuzun görselliğini artıracaktır. Bunun aksini yapsanız da sorgunuz sorunsuz çalışır. Hemen verdiğimiz soruyu sorgulayalım. Sıkı durun sorgu biraz uzun olacak. JOIN bilginizi kullanırsanız anlamakta zorlanmazsınız:
SELECT first_name as isim, salary, c.country_name
FROM employees e JOIN departments d
ON e.department_ıd = d.department_ıd
JOIN locations l
ON d.locatıon_ıd = l.location_id
JOIN countries c
ON l.country_id = c.country_id
WHERE c.country_name =
(SELECT c.country_name
FROM employees e JOIN departments d
ON e.department_ıd = d.department_ıd
JOIN locations l
ON d.locatıon_ıd = l.location_id
JOIN countries c
ON l.country_id = c.country_id
WHERE e.fırst_name = 'Donald');
ISIM SALARY COUNTRY_NAME
-------------------- ----------------- ------------------------
Alexander 9000 United States of America
Bruce 6000 United States of America
David 4800 United States of America
...
68 rows selected
Kısaca açıklayalım: Alt sorgu bize 'Donald' isimli şahsın görevli olduğu ülkenin ismini döndürmektedir. Tek bir ülke ismi döner: United States of America. Dolayısıyla tekli karşılaştırma operatörlerini kullanmamız gerekir. Buradaki en ÖNEMLİ nokta burasıdır. Geri kalan bilgiler daha önceki SQL bilgileriniz ile alakalıdır. "Donald isimli kişinin çalıştığı ülke" sorgusundan sadece bir ülke ismi döner. Yani tek durumda normal eşitsizlik ifadelerini kullanmamız gerekir. Bunları hatırlarsak : =, >, <, >=, <=, <> şeklindeydi. Peki alt sorgudan birden çok sonuç dönmesi gerekiyorsa ne tür karşılaştırma operatörleri işimizi görür? Örneğin sorgudaki ismi 'John' ile değiştirirseniz hata mesajı ile karşılaşırsınız:
Error report:
SQL Error: ORA-01427: tek satırlık alt sorgu birden fazla satır döndürüyor
Yani tek satır operatörü olan = yetersiz kalıyor! = operatörünü IN ile değiştirirseniz sorununuz çözülecektir. Bu kez 103 tane sorgu sonucu gelir ki United Kingdom da sonuçlarınıza eklenmiştir. IN operatörünü hatırlıyor olmalısınız. Tek bir ifadeyi yani ana sorgudaki WHERE şartındaki country_name'i alt sorgudan dönen iki adet ülke ismiyle karşılaştırır. İkisinden biri ile eşleşiyorsa sorgu sonucunda yerini alacaktır.
Bu karmaşık örnekten sonra aklınıza yatması için bir de JOIN'siz basit bir örnek yapalım: Donald isimli kişinin maaşından daha az maaş alan çalışanların maaşlarını listeleyelim:
SELECT last_name, salary
FROM employees
WHERE salary <
(SELECT salary
FROM employees
WHERE first_name = 'Donald');
LAST_NAME SALARY
------------------------- ----------------------
Colmenares 2500
Landry 2400
Markle 2200
...
11 rows selected
Burada da küçüktür < operatörünün kullanımını görmüş oldunuz.
Şimdi öğrendiklerimizi toparlayalım.
Alt Sorgu Tipleri:
Döndürdükleri sonuç sayılarına göre ikiye ayrılırlar:
- Tek sonuç döndüren alt sorgular: 'Donald' isimli şahsın ülkesinde çalışan kişilerin maaşlarını çektiğimiz sorguda alt sorgudan tek sonuç dönmüştü. Bu gibi alt sorgudan tek sonucun döndüğü sorgulardır. Tekli karşılaştırma operatörleri ile kullanılırlar.Yani; eşittir (=), büyüktür (>), küçüktür (<), büyük eşittir (>=), küçük eşittir (<=), eşit değildir (<>) seçenekleri ile kullanım mümkündür.
Bu bilgilerin yanı sıra şu da önemlidir: Bir sorguda birden fazla alt sorgu kullanılabilir. Örneğin çalıştığı şehir 'Donald' ile aynı olan ve 'Susan' ile aynı maaşı alan çalışan kimse var mıymış bir bakalım:
SELECT e.first_name, l.city, salary
FROM employees e JOIN departments d
ON e.department_ıd = d.department_ıd
JOIN locations l
ON l.location_id = d.locatıon_ıd
WHERE l.city =
(SELECT city
FROM employees e JOIN departments d
ON e.department_ıd = d.department_ıd
JOIN locations l
ON l.location_id = d.locatıon_ıd
WHERE first_name = 'Donald')
AND e.salary =
(SELECT salary
FROM employees
WHERE first_name = 'Susan');
FIRST_NAME CITY SALARY
-------------------- ------------------------------ ---------
Shanta South San Francisco 6500
1 rows selected
Azıcık zor gibi görünüyor ama hiç de öyle değil :) Eğer yapmakta güçlük çekiyorsanız alt sorguları ayrı bir kenarda tasarlayın. Daha sonra bu sorguları ana sorgunuz ile birleştirin. - Çok sonuç döndüren alt sorgular: Ana sorguya bir satırdan daha fazla sonuç gönderir. Çok satırlı operatörlerle birlikte kullanılmalıdır! Bu operatörlerden IN operatörünü öğrenmiştik. Şimdi diğer ikisini öğrenelim:
- ANY: Bir değeri alt sorgudan dönen bir dizi sonuçla karşılaştırır. Hiçbir satır dönmezse FALSE değeri döndürür. =ANY, != ANY, > ANY, < ANY, <= ANY ve >= ANY ile kullanılır. Örneğin bir değer alt sorgudan dönen herhangi bir değere eşit mi sorusunu =ANY ile araştırırız. Eğer eşit olan bir değer yoksa FALSE değerini görürsünüz.
- ALL: Bir değeri alt sorgudan dönen bir dizi sonuçla karşılaştırır. Hiçbir satır dönmezse TRUE değeri döndürür. Yine ANY ile aynı operatörlerle kullanılır.
Diğer Notlar:
- Alt sorgularda grup fonksiyonlarını kullanabilirsiniz. Örneğin IT_PROG job_id'sine sahip olan çalışanların en yüksek maaş alanından daha yüksek maaş alan çalışanları görelim:
SELECT last_name, job_id, salary
FROM employees
WHERE salary >
(SELECT MAX(salary)
FROM employees
WHERE job_id = 'IT_PROG');
LAST_NAME JOB_ID SALARY
------------------------- ---------- ----------------------
Hartstein MK_MAN 13000
Baer PR_REP 10000
...
23 rows selected - Ana sorguda GROUP BY ve HAVING ifadelerini kullandığınızda HAVING kısmında alt sorgu kullanmanız sıkıntı oluşturmaz. Ancak alt sorguda GROUP BY ifadesini kullanıyorsanız ana sorguda kesinlikle tekli karşılaştırma operatörlerini kullanamazsınız. Aşağıdaki sorgu hata verecektir:
SELECT first_name, last_name
FROM employees
WHERE salary =
(SELECT MIN(salary)
FROM employees
GROUP BY department_id);
Error report:
SQL Error: ORA-01427: tek satırlık alt sorgu birden fazla satır döndürüyor - İç sorgudan herhangi bir sonuç alınamazsa yada NULL ifadesi geri dönerse; o zaman ana sorgu da herhangi bir sonuç döndürmez.
job_id'si 'ST_CLERK' olmayıp, job_id'si 'ST_MAN' olan çalışanlardan daha çok maaş alan çalışanların bilgilerini görüntüleyelim:
SELECT employee_id, first_name, job_id, salary
FROM employees
WHERE salary > ANY
(SELECT salary
FROM employees
WHERE job_id = 'ST_MAN')
AND job_id <> 'ST_CLERK';
EMPLOYEE_ID FIRST_NAME JOB_ID SALARY
---------------------- -------------------- ---------- ----------
100 Steven AD_PRES 24000
101 Neena AD_VP 17000
102 Lex AD_VP 17000
...
57 rows selected
Aynı sorguyu ALL operatörü ile kullanıp sonuçları yorumlayalım:
SELECT employee_id, first_name, job_id, salary
FROM employees
WHERE salary > ALL
(SELECT salary
FROM employees
WHERE job_id = 'ST_MAN')
AND job_id <> 'ST_CLERK';
EMPLOYEE_ID FIRST_NAME JOB_ID SALARY
---------------------- -------------------- ---------- ----------------------
206 William AC_ACCOUNT 8300
177 Jack SA_REP 8400
...
37 rows selected
Bu da demek oluyor ki job_id'si 'ST_CLERK' olmayıp, job_id'si 'ST_MAN' olan çalışanlarının aldığı en yüksek maaştan daha çok maaş alan çalışanların bilgilerini görmek istiyoruz... Zaten ALL ifadesi için şu formülü aklınızda tutun:
- > ALL : En büyükten daha büyük
- < ALL : En küçükten daha küçük
- > ANY: En büyükten daha küçük
- < ANY: En küçükten daha büyük
- = ANY: IN ile aynı
Bu konuyu da burada noktalayabiliriz. Kolay gelsin!
Hiç yorum yok:
Yorum Gönder