Gereksinimler ve Ön Hazırlık
İleri seviye SQL sorguları yazabilmek için modern bir veritabanı motoruna ihtiyacınız vardır. MySQL 8.0 ve üzeri, PostgreSQL 14+ veya SQL Server 2022 gibi güncel sürümler, bu rehberde kullanılan pencere fonksiyonlarını (window functions) ve CTE yapılarını tam olarak destekler.
- Veritabanı Motoru: Pencere fonksiyonlarını destekleyen güncel bir RDBMS.
- Veri Seti: Analiz yapabilmek için en az 10.000 satırlık bir satış veya log tablosu.
- Araçlar: DBeaver, pgAdmin veya benzeri gelişmiş bir SQL yönetim arayüzü.
Çalışmalarınıza başlamadan önce veritabanı kullanıcınızın sadece SELECT yetkisine sahip olduğundan emin olun. Analiz süreçlerinde veriyi değiştirmemek (Read-Only erişim), veri bütünlüğünü korumak adına en iyi pratiktir.
Ortak Tablo İfadeleri (CTE) ile Sorgu Okunabilirliğini Artırma
Karmaşık sorguları parçalara ayırmak, hata ayıklamayı kolaylaştırır. WITH anahtar kelimesi ile oluşturulan Ortak Tablo İfadeleri (Common Table Expressions), geçici sonuç kümeleri oluşturmanıza olanak tanır. Bu yöntem, iç içe geçmiş karmaşık SELECT sorgularından çok daha temizdir.
WITH AylikSatislar AS (
SELECT
EXTRACT(MONTH FROM satis_tarihi) AS ay,
SUM(tutar) AS toplam_tutar
FROM satislar
WHERE satis_tarihi >= '2026-01-01'
GROUP BY 1
)
SELECT ay, toplam_tutar
FROM AylikSatislar
WHERE toplam_tutar > 50000;
Yukarıdaki örnekte, önce yılın aylık satışlarını hesaplayan bir sanal tablo oluşturduk, ardından bu tabloyu ana sorgumuzda filtreledik. Bu yapı, özellikle raporlama süreçlerinde kodun okunabilirliğini %50 oranında artırır.
Pencere Fonksiyonları ile Sıralı Analizler Yapma
Pencere fonksiyonları, satırları gruplandırmadan (GROUP BY kullanmadan) satır bazlı hesaplamalar yapmanızı sağlar. OVER() yan tümcesi, veriyi belirli bir pencereye böler ve hesaplamayı bu pencere üzerinde gerçekleştirir.
SELECT
urun_adi,
kategori,
tutar,
AVG(tutar) OVER(PARTITION BY kategori) as kategori_ortalama
FROM urunler;
Bu sorgu, her ürünün kendi kategorisindeki ortalama fiyatla yan yana görünmesini sağlar. PARTITION BY ifadesi, veriyi kategorilere göre böler ve her kategori için ayrı bir ortalama hesaplar. Bu, pazar analizi yaparken ürünlerin performansını kıyaslamak için mükemmel bir yöntemdir.
Kümülatif Toplam ve Hareketli Ortalamalar
Finansal analizlerde, zaman serisi verileri üzerinden kümülatif (birikimli) toplam almak oldukça yaygındır. SUM() OVER(ORDER BY ...) yapısı, veritabanı seviyesinde bu hesaplamayı saniyeler içinde yapar.
SELECT
satis_tarihi,
tutar,
SUM(tutar) OVER(ORDER BY satis_tarihi) as kümülatif_toplam
FROM satislar;
Bu kod, her gün yapılan satışın o güne kadar olan toplamını hesaplar. Eğer 7 günlük hareketli ortalama almak isterseniz, ROWS BETWEEN 6 PRECEDING AND CURRENT ROW ifadesini ekleyerek pencereyi daraltabilirsiniz.
Veri Analizinde Karşılaştırmalı Yöntemler
Aşağıdaki tablo, analiz süreçlerinde hangi SQL yönteminin ne zaman kullanılacağını özetlemektedir:
| Yöntem | Avantaj | Dezavantaj |
|---|---|---|
| CTE (WITH) | Yüksek okunabilirlik | Çok büyük veride performans kaybı olabilir |
| Window Functions | Satır bazlı detaylı analiz | Öğrenme eğrisi yüksektir |
| Subquery | Hızlı ve basit | İç içe geçince karmaşıklaşır |
SQL Analizlerinde Güvenlik ve Performans İpuçları
İleri seviye sorgular yazarken veritabanı sunucusunu yormamak gerekir. SELECT * kullanımından kaçınmalı, sadece ihtiyacınız olan sütunları çağırmalısınız. Ayrıca, analiz sorgularınızda EXPLAIN ANALYZE kullanarak sorgu planını inceleyin ve indeksleme eksiklerini tespit edin.
Kritik Uyarı: Analiz sorgularınızda asla kullanıcıdan gelen ham veriyi doğrudan sorgu içine gömmeyin. SQL Injection riskine karşı her zaman "Prepared Statements" (Hazırlanmış İfadeler) kullanın. Üretim ortamında (production) büyük veri setleri üzerinde çalışırken LIMIT kullanmayı ihmal etmeyin.
Sıkça Sorulan Sorular
Pencere fonksiyonları her veritabanında çalışır mı?
Modern RDBMS sistemlerinin %95'i pencere fonksiyonlarını destekler. Ancak, çok eski sürümlerde (örneğin MySQL 5.7 öncesi) bu özellik bulunmaz.
CTE kullanmak sorguyu yavaşlatır mı?
Modern optimizasyon motorları CTE'leri genellikle bir alt sorgu gibi işler. Ancak, çok büyük veri setlerinde CTE'lerin geçici tablo gibi davranması performansı etkileyebilir.
İndeksleme analiz sorgularını nasıl etkiler?
Doğru indeksleme, PARTITION BY veya ORDER BY kullanılan sorgularda işlem süresini milisaniyelere indirebilir.
Neden GROUP BY yerine Window Function tercih etmeliyim?
GROUP BY veriyi sıkıştırır ve detayları kaybedersiniz. Pencere fonksiyonları ise detay veriyi koruyarak yanına hesaplanmış değerleri eklemenize imkan tanır.
Büyük veri setlerinde analiz yaparken nelere dikkat etmeliyim?
Bellek yönetimi kritiktir. Mümkünse veriyi filtreleyerek (WHERE ile) sorguya sokun ve veritabanı sunucusunun kaynaklarını tüketmemeye özen gösterin.
SQL Sorgularında Hata Ayıklama ve Optimizasyon Stratejileri
İleri seviye analiz sorguları yazarken karşılaşılan en büyük zorluk, sorgunun mantıksal doğruluğundan ziyade, karmaşık birleşmelerin (JOIN) veya pencere fonksiyonlarının beklenmedik sonuçlar üretmesidir. Hata ayıklama sürecini hızlandırmak için sorgunuzu parçalara ayırarak ilerlemek en güvenli yöntemdir.
Sorgu Planı Analizi (EXPLAIN Plan)
Sorgunuzun veritabanı motoru tarafından nasıl işlendiğini anlamak, performans sorunlarını kökünden çözmenizi sağlar. EXPLAIN komutu, veritabanının hangi indeksleri kullandığını ve hangi aşamada tam tablo taraması (Full Table Scan) yaptığını gösterir.
-- Sorgu planını incelemek için
EXPLAIN ANALYZE
SELECT
category_id,
AVG(price) OVER(PARTITION BY category_id) as avg_price
FROM products
WHERE status = 'active';
Eğer analiz sonucunda Seq Scan (Sıralı Tarama) görüyorsanız, ilgili sütunlarda indeks eksikliği yaşıyor olabilirsiniz. Özellikle PARTITION BY içerisinde kullanılan sütunlara indeks eklemek, pencere fonksiyonlarının çalışma süresini ciddi oranda düşürür.
SQL Analizlerini Otomatize Etme: Stored Procedures ve Views
Tekrarlayan analiz sorgularını her seferinde manuel olarak çalıştırmak yerine, bunları veritabanı nesneleri olarak saklamak iş akışınızı optimize eder. Görünümler (Views), karmaşık analiz sorgularını sanki bir tabloymuş gibi sorgulamanıza olanak tanır.
Dinamik Analiz İçin View Kullanımı
Aşağıdaki örnekte, karmaşık bir satış analizini bir VIEW haline getirerek, raporlama araçlarının bu veriyi kolayca tüketmesini sağlıyoruz:
CREATE OR REPLACE VIEW monthly_sales_performance AS
SELECT
DATE_TRUNC('month', order_date) as sales_month,
region,
SUM(amount) as total_revenue,
SUM(SUM(amount)) OVER(PARTITION BY region ORDER BY DATE_TRUNC('month', order_date)) as running_total
FROM orders
GROUP BY 1, 2;
-- Artık basit bir sorgu ile analize ulaşabilirsiniz:
SELECT * FROM monthly_sales_performance WHERE sales_month >= '2023-01-01';
Bu yöntem, özellikle BI (İş Zekası) araçları ile çalışırken veritabanı katmanında bir soyutlama sağlar. Analiz mantığınız değiştiğinde, sadece VIEW tanımını güncellemeniz yeterlidir; uygulamadaki sorguları değiştirmenize gerek kalmaz.
Analitik Sorgularda Hata Yönetimi
Büyük veri setlerinde Division by zero (sıfıra bölme) veya NULL değerler analizinizi bozabilir. Bu tür durumları NULLIF ve COALESCE fonksiyonları ile yönetmek profesyonel bir standarttır.
- NULLIF: İkinci değer birinciye eşitse NULL döner, böylece sıfıra bölme hatalarını engeller.
- COALESCE: NULL değerleri varsayılan bir değerle (örneğin 0) değiştirir.
SELECT
product_name,
total_sales / NULLIF(total_units, 0) as unit_price
FROM inventory;
Bu yaklaşım, veri setinizdeki eksik veya hatalı kayıtların tüm raporlama zincirini çökertmesini engeller ve analizlerinizin sürekliliğini sağlar.
Sonuç
Sql & Veritabanı ile ileri seviye veri analizi sorgusu yapmak, verinin gücünü keşfetmenin en etkili yoludur. Bu rehberde öğrendiğiniz CTE yapıları, pencere fonksiyonları ve kümülatif hesaplamalar, profesyonel bir veri analisti veya yazılımcı olarak size büyük bir hız kazandıracaktır. Bir sonraki adımda, bu sorguları bir BI (İş Zekası) aracına bağlamayı veya veritabanı üzerinde VIEW (Görünüm) oluşturarak bu sorguları kalıcı hale getirmeyi deneyebilirsiniz. Sürekli pratik yaparak SQL yetkinliklerinizi bir üst seviyeye taşıyabilirsiniz.

Yorumlar (16)
Okurken keyif aldım, SQL bilmeyen birine bile anlatır gibi yazmışsın. Tebrikler.
Anlatım tarzın çok akıcı, daha önce çok yerde okudum ama böyle net anlatan görmedim valla.
Katılıyorum, gerçekten basit ve öz bir anlatım olmuş.
Veri analitiği mülakatlarında sorulan sorulara çok iyi bir giriş olmuş. Teşekkürler.
Ya bu kod bloklarını kopyalayınca bazen tırnak işaretleri bozuluyor, fark ettiniz mi? Onun dışında her şey harika.
Geri bildirim için teşekkürler Elifnur, hemen kontrol ediyorum.
Sorgu performansını artırmak isteyen herkesin okuması gereken bir yazı. Kalemine sağlık Kerem.
Yazı güzelde PostgreSQL üzerinde denedim bazı fonksiyonlar çalışmadı, versiyon farkı olabilir mi?
Versiyon farkı olabilir, kullandığınız sürümü belirtirseniz yardımcı olmaya çalışırım.
SQL'de hep subquery kullanıyordum, CTE'ler gerçekten hayat kurtarıyor. Çok temiz oldu kodlarım.
Performans optimizasyonu kısmında biraz daha örnek verebilirdin sanki. Yine de kaliteli bir içerik olmuş.
Haklısın Fatih, bir sonraki yazımda execution plan okuma üzerine odaklanarak daha teknik detaylara gireceğim.
Ya bu window functions olayı benim kafamı çok karıştırıyodu, sade anlatımın için çok sağol. Nerdeyse çözdüm mantığı.
Aynen, ilk başta karmaşık geliyor ama alışınca bırakamıyorsun.
Hocam eline sağlık, CTE kullanımı projelerimde çok işime yarıyor artık. Pencere fonksiyonları için de ayrı bir yazı bekliyorum.
Teşekkürler Caner, pencere fonksiyonlarını derinlemesine işleyeceğim bir sonraki yazı yolda!
Yorum Yaz