- Bir Alt Sorgu başka bir SELECT, INSERT, UPDATE veya DELETE ifadesi içerisine yuvalanmış bir SELECT ifadesidir.
- Çoğu durumda alt sorguları JOIN ifadelerine dönüştürebilirsiniz.
- Alt sorgular, karmaşık sorguları biraz daha anlaşılabilir mantıksal bölümlere ayırmak için veya birbaşka sorgunun sonuç kümesine dayalı bir sorguyu çalıştırmak için kullanılır.
- JOIN bağlantıları Alt Sorgulardan daha hızlı işlenirler.
- Kural olarak ise Alt Sorguları parantez içinde yazmalıyız.
Sonuç Kümesinin Tablo Olarak Kullanımı : Sorguda FROM ifadesinde kullanılan tablonun yerine bir başka sorguyu kullanabilirsiniz. Sonuç Kümesine herhangi bir tabloya yapabildiğimiz gibi bir geçici takma ad verilebilir.
SELECT T.ORDERID, T.CUSTOMERID
FROM (SELECT ORDERID, CUSTOMERID FROM orders) AS T
Sonuç Kümesinin Bir Deyim Olarak Kullanılması : SQL de bir sorguyu herhangi bir deyimin yerine
kullanabilirsiniz. Bu amaç için kullanılacak bir sorgu tek bir sayısal değer
veya tek bir sütun değer listesi döndürmelidir. Bir değerler listesi geri
döndüren sorgular IN anahtar kelimesi içeren WHERE yantümcesi yerine
kullanılabilir.
Ortalamayı bulup satılan ürünlerimiz için ayrıntılı birim fiyatlarını ve bu birim fiyatlarının ortalama ürün fiyatına oranla durumunu gösterelim.
SELECT ProductName AS 'ÜRÜN ADI',UnitPrice AS 'BİRİM FİYATI', UnitsInStock AS 'STOK',
(SELECT AVG(UnitPrice) FROM Products) AS ORTALAMA,
UnitPrice-(SELECT AVG(UnitPrice) FROM Products) AS FARK FROM Products
(SELECT AVG(UnitPrice) FROM Products) AS ORTALAMA,
UnitPrice-(SELECT AVG(UnitPrice) FROM Products) AS FARK FROM Products
İlişkili Alt Sorgu : İç sorgu ile dış sorgu bir alan üzerinden doğrudan bağlantılıdır.
30 nolu üründen 30 dan fazla sipariş veren müşterileri listeleyelim.
SELECT OrderID, CustomerID FROM orders AS or1
WHERE 30<(SELECT quantity FROM [order details] AS od
WHERE or1.OrderID=od.OrderID AND od.ProductID=30)
WHERE 30<(SELECT quantity FROM [order details] AS od
WHERE or1.OrderID=od.OrderID AND od.ProductID=30)
Alt Sorgu-JOIN Dönüşümü : İlişkili alt sorguları bir JOIN ifadesi yerine kullanabiliriz.
İki farklı sorgu aynı sonucu vermektedir. Birinci örnekte Alt Sorgu kullanılmış, ikinci sorguda aynı sonuca JOIN ile ulaşılmıştır.
SELECT DISTINCT E1.TitleOfCourtesy FROM Employees AS E1
WHERE E1.City IN
(SELECT E2.City FROM Employees AS E2 WHERE E1.TitleOfCourtesy<>E2.TitleOfCourtesy)
WHERE E1.City IN
(SELECT E2.City FROM Employees AS E2 WHERE E1.TitleOfCourtesy<>E2.TitleOfCourtesy)
SELECT DISTINCT E1.TitleOfCourtesy FROM Employees AS E1
INNER JOIN Employees AS E2 WITH (NOLOCK) ON E1.City=E2.City
WHERE E1.TitleOfCourtesy<>E2.TitleOfCourtesy
INNER JOIN Employees AS E2 WITH (NOLOCK) ON E1.City=E2.City
WHERE E1.TitleOfCourtesy<>E2.TitleOfCourtesy
Alt Sorgu-HAVING Dönüşümü : İlişkili bir alt sorgunun ürettiği sonuç kümesini HAVING ile de elde edebiliriz.
SELECT ProductName,CategoryID,UnitPrice FROM Products AS p1
WHERE p1.UnitPrice>(SELECT AVG(UnitPrice) FROM Products AS p2
WHERE p1.CategoryId=p2.CAtegoryId) ORDER BY CategoryId
WHERE p1.UnitPrice>(SELECT AVG(UnitPrice) FROM Products AS p2
WHERE p1.CategoryId=p2.CAtegoryId) ORDER BY CategoryId
SELECT p1.ProductName,p1.CategoryID,p1.UnitPrice FROM Products AS p1
INNER JOIN Products AS p2 WITH (NOLOCK) ON p1.CategoryID=p2.CategoryID
GROUP BY p1.ProductName,p1.CategoryID,p1.UnitPrice
HAVING p1.UnitPrice>AVG(p2.UnitPrice) ORDER BY p1.CategoryId
INNER JOIN Products AS p2 WITH (NOLOCK) ON p1.CategoryID=p2.CategoryID
GROUP BY p1.ProductName,p1.CategoryID,p1.UnitPrice
HAVING p1.UnitPrice>AVG(p2.UnitPrice) ORDER BY p1.CategoryId
EXISTS ve NOT EXISTS İşlevleri : Bazı durumlarda Alt Sorguların ürettikleri değerler ile değil, sorgunun sonucunun var olup olmadığıyla ilgileniriz. EXIST ve NOT EXIST işlevleri, bu sorgulamayı yapmak için kullanılır ve DOĞRU (TRUE) veya YANLIŞ (FALSE) değeri döndürür.
Birinci sorguda ‘3/05/1998’ ve '4/05/1998' tarihleri arasında sipariş almış olan çalışanlar EXIST işlevi ile listeliyoruz. Aynı sonuca JOIN ile birleştirerekte ulaşabiliriz.
SELECT EmployeeId,LastName,FirstName
FROM Employees AS e WHERE EXISTS
(SELECT * FROM Orders AS o
WHERE e.EmployeeId=o.EmployeeId
AND o.OrderDate BETWEEN '3/5/1998' AND '4/5/1998')
FROM Employees AS e WHERE EXISTS
(SELECT * FROM Orders AS o
WHERE e.EmployeeId=o.EmployeeId
AND o.OrderDate BETWEEN '3/5/1998' AND '4/5/1998')
SELECT DISTINCT FirstName,LastName, e.EmployeeID
FROM Orders AS o
INNER JOIN Employees AS e
ON o.EmployeeID =e.EmployeeID
WHERE o.OrderDate BETWEEN '3/5/1998' AND '4/5/1998'
FROM Orders AS o
INNER JOIN Employees AS e
ON o.EmployeeID =e.EmployeeID
WHERE o.OrderDate BETWEEN '3/5/1998' AND '4/5/1998'