SQL CTE Nedir? WITH Kullanımı ve Recursive CTE Örnekleri
CTE, karmaşık bir sorgu içinde geçici ve isimlendirilmiş bir sonuç kümesi tanımlamayı sağlar. Açılımı Common Table Expression’dır ve WITH ifadesiyle yazılır.
CTE fiziksel bir tablo oluşturmaz. Tanımlandığı sorgu kapsamında kullanılabilir.
Temel CTE örneği
WITH CustomerSales AS (
SELECT
CustomerID,
SUM(Amount) AS TotalAmount
FROM Orders
GROUP BY CustomerID
)
SELECT
CustomerID,
TotalAmount
FROM CustomerSales
WHERE TotalAmount > 10000;
Önce müşteri toplamları hesaplanır, ardından ana sorguda 10.000 üzerindeki müşteriler filtrelenir.
CTE neden kullanılır?
- İç içe alt sorguları okunabilir hâle getirir.
- Dönüşüm adımlarına anlamlı isim verir.
- Aynı sorguda çok aşamalı hesaplama kurmayı kolaylaştırır.
- Hiyerarşik veriler için recursive sorgu yazmayı sağlar.
- Karmaşık SQL kodunun test edilmesini kolaylaştırır.
CTE ve alt sorgu farkı
Aynı sonuç çoğu zaman alt sorguyla da üretilebilir:
SELECT *
FROM (
SELECT CustomerID, SUM(Amount) AS TotalAmount
FROM Orders
GROUP BY CustomerID
) s
WHERE TotalAmount > 10000;
CTE’nin temel avantajı okunabilirlik ve adımları ayırmaktır. CTE kullanmak sorgunun otomatik olarak daha hızlı çalışacağı anlamına gelmez; veritabanı yürütme planı ayrıca incelenmelidir.
Birden fazla CTE kullanımı
WITH MonthlySales AS (
SELECT
CustomerID,
YEAR(OrderDate) AS SalesYear,
MONTH(OrderDate) AS SalesMonth,
SUM(Amount) AS MonthlyAmount
FROM Orders
GROUP BY
CustomerID,
YEAR(OrderDate),
MONTH(OrderDate)
),
CustomerAverage AS (
SELECT
CustomerID,
AVG(MonthlyAmount) AS AvgMonthlyAmount
FROM MonthlySales
GROUP BY CustomerID
)
SELECT *
FROM CustomerAverage
ORDER BY AvgMonthlyAmount DESC;
CTE’ler virgülle ayrılır; ikinci CTE önceki CTE’nin sonucunu kullanabilir.
Recursive CTE nedir?
Recursive CTE kendi sonucuna tekrar başvurarak hiyerarşik yapıları dolaşır. Organizasyon şeması, ürün ağacı ve kategori hiyerarşisi örnektir.
WITH EmployeeTree AS (
SELECT
EmployeeID,
ManagerID,
EmployeeName,
0 AS LevelNo
FROM Employees
WHERE ManagerID IS NULL
UNION ALL
SELECT
e.EmployeeID,
e.ManagerID,
e.EmployeeName,
t.LevelNo + 1
FROM Employees e
INNER JOIN EmployeeTree t
ON e.ManagerID = t.EmployeeID
)
SELECT *
FROM EmployeeTree;
İlk bölüm başlangıç kayıtlarını, ikinci bölüm bir sonraki seviyeyi bulur.
CTE kullanırken sık yapılan hatalar
CTE’yi kalıcı tablo sanmak
CTE yalnızca kendisini takip eden ifade kapsamında geçerlidir.
Sıralamanın korunduğunu varsaymak
Sonuç sırası gerekiyorsa ana SELECT içinde ORDER BY kullanın.
Recursive CTE’de bitiş koşulu kurmamak
Hatalı ilişki veya döngü gereksiz tekrar oluşturabilir. Hiyerarşi anahtarlarını doğrulayın.
Büyük sonucu tekrar tekrar kullanmak
CTE her senaryoda ara sonucu fiziksel olarak saklamaz. Sonuç birçok kez kullanılacaksa geçici tablo veya farklı tasarım daha uygun olabilir.
CTE ne zaman kullanılmalı?
- Adım adım okunması gereken rapor sorgularında
- Önce toplulaştırıp sonra filtreleme yapılacağında
- Window function sonucuna ek filtre uygulanacağında
- Hiyerarşik veri çözüleceğinde
JOIN temelini güçlendirmek için SQL JOIN türleri rehberini okuyun. Sorguları interaktif SQL eğitiminde deneyebilirsiniz.
Sık sorulan sorular
CTE view ile aynı şey mi?
Hayır. View veritabanında tanımlanan kalıcı bir nesnedir; CTE tek sorgu kapsamında yaşar.
CTE performansı artırır mı?
Tek başına performans garantisi vermez. Okunabilirliği artırır; gerçek performans yürütme planı, indeksler ve veri hacmine bağlıdır.
CTE içinde JOIN kullanılabilir mi?
Evet. SELECT içinde kullanılabilen JOIN, GROUP BY ve window function gibi yapılar CTE içinde de kullanılabilir.