Alt sorgu, başka bir sorgu içerisinde bulunan SELECT ifadesidir. Bir sorguyu diğerinin içine yerleştirerek, T-SQL’de etkili sorgular oluşturabilirsiniz. Bu bölümde, bağımsız sorguları ve bu sorgulardan dönen sonuçların dış katmandaki sorguya nasıl gönderileceğini öğreneceğiz. Ayrıca, tek değer döndüren veya birden çok değer döndüren alt sorgu sonuçlarını dıştaki sorguya nasıl döndürebildiğini de göreceğiz.

 Alt Sorgularla Çalışmak

Alt sorgu, başka bir sorgu içerisinde iç içe veya gömülü bir SELECT ifadesidir. Gömülü alt sorguya iç sorgu denir. İç sorguyu barındıran sorguya da dış sorgu denir.

Alt sorgunun amacı, dönen sonuçları dış sorguya vermektir. Dönen sonucun şekli, alt sorgunun skaler mi yoksa birden fazla değer döndüren (multi-valued) bir alt sorgu olup olmadığını belirler:

  • Skaler alt sorgular, skaler fonksiyonlar gibi, tek bir değer döndürür. Sonucu işlemek için dış sorguların yazılması gerekir.
  • Multi-valued alt sorgular, tek sütunlu tabloya benzer bir sonuç döndürür. Olası çok sayıda sonucu işlemek için dış sorguların yazmak gerekir.

Skaler ve multi-valued alt sorgulara ek olarak, bağımsız veya dış sorguyla bağlantılı alt sorgular da yazabilirsiniz:

  • Bağımsız alt sorgular, dış sorguya bağımlı olmadan yazılabilir. Dış sorgu çalıştığında ve sonuçlarını bu dış sorguya ilettiğinde, bağımsız bir alt sorgu bir kez işlenir.
  • İlişkili alt sorgular, dış sorgudan bir veya daha fazla sütunla işlem yaptığından dış sorguyla ilişkilidir. İlişkili alt sorgular, dış sorgudan ayrı olarak çalıştırılamaz.
Skaler Alt Sorgular

Skaler alt sorgu, dış sorguya tek bir değer döndüren bir SELECT ifadesidir. Skaler alt sorgular, dış T-SQL sorgusunda tek değerlerin kullanıldığı herhangi bir yerde kullanılabilir. Örneğin SELECT, WHERE, HAVING ve FROM gibi yerlerde.

Bir skaler alt sorgu yazmak için aşağıdakileri dikkate almakta fayda var:

  • Bir sorguyu alt sorgu olarak tanımlamak için parantez içine alınması gerekir.
  • SQL Server’da birden çok alt sorgu yazılabilir. Bu bölümde yalnızca iki katmanlı sorguları (bir dış sorgu ve barındırdığı iç sorgu) ele alacağız. SQL Server’da 32 seviyeye kadar sorgu yazılabilir.
  • Alt sorgu boş bir küme döndürürse, alt sorgunun sonucu NULL değere dönüştürülür ve böyle döndürülür.
  • Dış sorgunuzun, diğer işlemlere ek olarak NULL değeri de işleyebildiğinden emin olmanız gerekli.

İlk başta örnek olarak TSQL veri tabanı kullanılan bir iç sorgu yazalım:

USE TSQL;
GO
SELECT MAX(orderid) AS lastorder
FROM Sales.Orders;

Dönen sonuç:

lastorder
---------
11077 

Daha sonra, iç sorgu tarafından döndürülen değeri kullanacak olan dış sorguyu yazalım. Bu sorguda en son siparişle ilgili verileri çekilir:

SELECT orderid, productid, unitprice, qty
FROM Sales.OrderDetails
WHERE orderid =
 (SELECT MAX(orderid) AS lastorder
 FROM Sales.Orders);

Dönen kısmi tablo:

orderid productid unitprice qty
----------- ----------- --------------------- ------
11077 2 19.00 24
11077 3 10.00 4
11077 4 22.00 1
11077 6 25.00 1 

Alt sorgunun tek değer döndüreceğinden emin olmak için mantığını test edin. Yukarıdaki sorguda, dış sorgu WHERE ifadesi predicate’inde bir eşittir (=) işleci kullandığından ve alt sorgu tek bir değer döndürdüğünden, sorgu doğru şekilde çalıştı. Basit eşitlik operatörleri (=, <,> ve <> gibi) kullanarak tek değer işleyen dış sorgu varken iç sorgu birden fazla sonuç döndürürse hata oluşur:

Msg 512, Level 16, State 1, Line 1
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression. 

Sales.Orders tablosunda orderid sütunu primary key kısıtlamasına sahiptir.

Multi-valued Alt Sorgular

Adından da anlaşılacağı gibi, multi-valued bir alt sorgu, tek sütunlu küme biçiminde birden fazla sonuç döndürür.

Aşağıdaki örnekte olduğu gibi, Multi-valued alt sorgudan dönen sonuç, IN predicate’ine döndürülür:

SELECT custid, orderid
FROM Sales.orders
WHERE custid IN (
 SELECT custid
 FROM Sales.Customers
 WHERE country =N'Mexico');

Önceki örnekte bulunan iç sorguyu çalıştırdığımızda, Meksika ülkesindeki müşteri kayıtları dönecektir:

custid
------
2
3
13
58
80 

SQL Server bu sonuçları mantıksal olarak aşağıdaki gibi dış sorguya iletir:

SELECT custid, orderid
FROM Sales.orders
WHERE custid IN (2,3,13,58,80); 

Dış sorgu aşağıdaki gibi, alınan sonuçlarla SELECT ifadesini işlemeye devam eder ve nihai sonuç kümesi ortaya çıkar:

custid orderid
------ -----------
2 10308
2 10625
3 10365
3 10507
3 10856
13 10259
58 10322
58 10354 

Sorgularda multi-valued alt sorguların JOIN kullanarak yazılabilir.

Örneğin, önceki alt sorgu, aynı sonuçları döndürecek ve yaklaşık olarak aynı performansla çalışacak şekilde yeniden yazılabilir:

SELECT c.custid, o.orderid
FROM Sales.Customers AS c JOIN Sales.Orders AS o
 ON c.custid = o.custid
WHERE c.country = N'Mexico‘; 

Not: Bazı durumlarda, veri tabanı motoru bir alt sorguyu JOIN olarak yorumlar ve sorguyu buna göre yürütür. Execution plan gibi SQL Server’ın derinine indikçe sorgularınızın bu şekilde çalıştırıldığını görebilirsiniz.

Kaynak:
Subquery Fundamentals