Dünkü temellere şimdi analiz becerileri ekliyoruz. Sıralama, gruplama, toplam-ortalama hesaplama ve veriyi şekillendirme — bunlar T-SQL’in günlük ekmek peyniri.
1. ORDER BY — Sıralama
SELECT Name, Salary FROM Employees
ORDER BY Salary DESC;
ASC— Artan (varsayılan)DESC— Azalan
Birden Fazla Kritere Göre
SELECT * FROM Employees
ORDER BY Department ASC, Salary DESC;
-- Önce departmana göre artan, aynı departmandakileri maaşa göre azalan
Sütun Numarasıyla (kısa ama dikkat)
SELECT Name, Department, Salary FROM Employees
ORDER BY 3 DESC; -- 3. sütun = Salary
Production’da sütun adı yaz — sütun pozisyonu değişirse sorgun bozulur.
2. Sayfalama: OFFSET / FETCH
SELECT * FROM Employees
ORDER BY Id
OFFSET 20 ROWS
FETCH NEXT 10 ROWS ONLY;
OFFSET 20— İlk 20’yi atlaFETCH NEXT 10— Sonraki 10’u getir
Sayfalama yaparken mutlaka
ORDER BYkullan. Yoksa sıra garanti değil, aynı sorguyu iki kez çalıştırınca farklı sonuçlar gelebilir.
3. Aggregate Fonksiyonlar
Birden fazla satırı tek değere indirgerler:
| Fonksiyon | Açıklama |
|---|---|
COUNT(*) | Satır sayısı (NULL dahil) |
COUNT(column) | NULL hariç satır sayısı |
SUM(column) | Toplam |
AVG(column) | Ortalama |
MIN(column) | En küçük |
MAX(column) | En büyük |
SELECT
COUNT(*) AS TotalEmployees,
AVG(Salary) AS AvgSalary,
MIN(Salary) AS MinSalary,
MAX(Salary) AS MaxSalary,
SUM(Salary) AS TotalSalary
FROM Employees;
4. GROUP BY — Gruplama
Veriyi sütun değerine göre grupla, sonra aggregate fonksiyon uygula:
SELECT Department, COUNT(*) AS Total, AVG(Salary) AS AvgSal
FROM Employees
GROUP BY Department;
Sonuç:
Department | Total | AvgSal
IT | 12 | 8500.00
Marketing | 8 | 6200.00
HR | 5 | 5800.00
Önemli Kural
GROUP BY kullandığında, SELECT’deki her sütun ya aggregate
fonksiyon içinde olmalı, ya da GROUP BY’da yer almalı:
-- ✗ HATA
SELECT Department, Name, COUNT(*) FROM Employees GROUP BY Department;
-- Name ne aggregate ne GROUP BY'da
-- ✓ Doğru
SELECT Department, COUNT(*) FROM Employees GROUP BY Department;
5. HAVING — Grup Filtresi
WHERE satırları filtreler, HAVING grupları:
SELECT Department, COUNT(*) AS Total
FROM Employees
GROUP BY Department
HAVING COUNT(*) > 5;
-- Sadece 5'ten fazla çalışanı olan departmanlar
WHERE vs HAVING
SELECT Department, COUNT(*) AS Total
FROM Employees
WHERE Active = 1 -- önce satırları filtrele
GROUP BY Department
HAVING COUNT(*) > 5; -- sonra grupları filtrele
Sıra: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY
6. DISTINCT — Benzersiz Değerler
SELECT DISTINCT Country FROM Employees;
-- Tekrar etmeyen ülkeler
SELECT DISTINCT Country, City FROM Employees;
-- Ülke-şehir benzersiz kombinasyonları
7. CASE WHEN — Koşullu Sütunlar
Sorgu içinde if/else mantığı:
SELECT
Name,
Salary,
CASE
WHEN Salary < 5000 THEN 'Düşük'
WHEN Salary BETWEEN 5000 AND 10000 THEN 'Orta'
WHEN Salary > 10000 THEN 'Yüksek'
ELSE 'Belirsiz'
END AS SalaryBracket
FROM Employees;
Aggregate ile Birlikte (Conditional Count)
SELECT
COUNT(*) AS Total,
SUM(CASE WHEN Salary > 10000 THEN 1 ELSE 0 END) AS HighEarners,
SUM(CASE WHEN Department = 'IT' THEN 1 ELSE 0 END) AS ITStaff
FROM Employees;
Tek sorguda birden fazla “alt-count” alabilirsin — pivot benzeri.
8. String Fonksiyonları
| Fonksiyon | Örnek | Sonuç |
|---|---|---|
LEN(s) | LEN('Hello') | 5 |
UPPER(s) | UPPER('abc') | 'ABC' |
LOWER(s) | LOWER('XYZ') | 'xyz' |
LTRIM, RTRIM | LTRIM(' hi') | 'hi' |
TRIM | TRIM(' hi ') | 'hi' |
SUBSTRING(s, start, len) | SUBSTRING('abcdef', 2, 3) | 'bcd' |
LEFT(s, n) | LEFT('abcdef', 3) | 'abc' |
RIGHT(s, n) | RIGHT('abcdef', 2) | 'ef' |
REPLACE(s, a, b) | REPLACE('abc', 'b', 'X') | 'aXc' |
CONCAT(a, b, c) | CONCAT('Hi', ' ', 'World') | 'Hi World' |
CHARINDEX(sub, s) | CHARINDEX('cd', 'abcdef') | 3 |
Örnek: E-posta Domain Çıkarma
SELECT
Email,
SUBSTRING(Email, CHARINDEX('@', Email) + 1, LEN(Email)) AS Domain
FROM Users;
9. Tarih Fonksiyonları
SELECT GETDATE(); -- şu an (DATETIME)
SELECT SYSDATETIME(); -- daha yüksek hassasiyet
-- Bileşenler
SELECT YEAR(HireDate), MONTH(HireDate), DAY(HireDate) FROM Employees;
-- Tarih aritmetiği
SELECT DATEADD(YEAR, 1, GETDATE()); -- 1 yıl ekle
SELECT DATEADD(MONTH, -6, GETDATE()); -- 6 ay çıkar
SELECT DATEADD(DAY, 30, HireDate);
-- İki tarih arası fark
SELECT DATEDIFF(YEAR, HireDate, GETDATE()) AS YearsWorked FROM Employees;
SELECT DATEDIFF(DAY, OrderDate, ShipDate) FROM Orders;
-- Formatlama (SQL Server 2012+)
SELECT FORMAT(GETDATE(), 'dd MMMM yyyy', 'tr-TR'); -- 27 Mayıs 2026
SELECT FORMAT(Salary, 'C', 'tr-TR'); -- ₺ formatı
Yaygın DATEDIFF Birimleri
YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, WEEK, QUARTER
Pratik Sorular
Soru 1: Her departmanın en yüksek maaşını listele.
SELECT Department, MAX(Salary) AS MaxSalary
FROM Employees
GROUP BY Department
ORDER BY MaxSalary DESC;
Soru 2: Ortalama maaşı 7000’den fazla olan departmanları getir.
SELECT Department, AVG(Salary) AS AvgSalary
FROM Employees
GROUP BY Department
HAVING AVG(Salary) > 7000;
Soru 3: Çalışanları maaşa göre 3 kategoriye ayır ve her kategorideki kişi sayısını ver.
SELECT
CASE
WHEN Salary < 5000 THEN 'Düşük'
WHEN Salary < 10000 THEN 'Orta'
ELSE 'Yüksek'
END AS Bracket,
COUNT(*) AS Total
FROM Employees
GROUP BY
CASE
WHEN Salary < 5000 THEN 'Düşük'
WHEN Salary < 10000 THEN 'Orta'
ELSE 'Yüksek'
END;
Soru 4: Son 1 yıl içinde işe alınan çalışanların ortalama maaşı.
SELECT AVG(Salary) AS RecentAvgSalary
FROM Employees
WHERE HireDate >= DATEADD(YEAR, -1, GETDATE());
Soru 5: En çok çalışanı olan ilk 5 departman.
SELECT TOP 5
Department,
COUNT(*) AS Total
FROM Employees
GROUP BY Department
ORDER BY Total DESC;
Günün Özeti
Bugün analitik sorgu becerilerini öğrendik:
ORDER BYveTOP / OFFSET / FETCHile sıralama ve sayfalama- Aggregate fonksiyonlar (
SUM,AVG,COUNT,MIN,MAX) GROUP BYile gruplama veHAVINGile grup filtrelemeDISTINCTile benzersiz değerlerCASE WHENile koşullu sütunlar (sorgu içi if/else)- String ve tarih fonksiyonları
Yarın Gün 3’te JOIN’lere geçiyoruz — birden fazla tabloyu birleştirip gerçek ilişkisel sorgular yazacağız.