İçeriğe geç
Educora
İleri18 dk15 / 22

CASE ve koşullu mantık

CASE WHEN ile sorgunun içinde “eğer… ise…” yaz, COALESCE ve NULLIF ile NULL değerleri yönet, koşullu toplama ile tabloyu pivot biçimine getir.

Kendini test et
Bu derste öğreneceklerin
  • Aramalı ve basit CASE ifadelerini SELECT ve ORDER BY içinde kullanmak
  • COALESCE ile NULL değerleri değiştirmek ve NULLIF ile sıfıra bölmeden korunmak
  • Koşullu toplama ile satırları sütunlara çeviren bir pivot rapor kurmak

E-okul sistemi bir puanı gösterirken yanına harf notunu da yazar: 94 “A”, 81 “B”. Çevrim içi mağaza ürünün yanına “stokta yok” yazar, okul müdürü ise sınıflara ve şehirlere göre öğrenci sayısını tek bir tabloda görmek ister. Bunların hepsi sorgunun içindeki koşullardır ve SQL'de CASE ifadesiyle yazılır. CASE, diğer programlama dillerindeki if gibidir; ama bir komut değil, değer döndüren bir ifadedir. Bu yüzden bir sütunun yazılabildiği her yerde kullanılabilir.

Aramalı CASE: CASE WHEN ... THEN ... END

VTYS WHEN koşullarını yukarıdan aşağıya denetler ve ilk doğru koşulun THEN değerini döndürür; kalanlara artık bakmaz. Hiçbir koşul doğru değilse ELSE değeri, ELSE yazılmamışsa NULL döndürülür. İfade her zaman END ile biter ve genellikle AS ile bir ad verilir.

SQL
SELECT s.first_name, e.score,
       CASE
         WHEN e.score >= 90 THEN 'A'
         WHEN e.score >= 80 THEN 'B'
         WHEN e.score >= 70 THEN 'C'
         ELSE 'D'
       END AS letter
FROM enrollments AS e
JOIN students AS s ON s.id = e.student_id
WHERE e.course_id = 3
ORDER BY e.score DESC;
▸ Beklenen çıktı
first_name | score | letter
Fidan | 94 | A
Murad | 81 | B
Rəşad | 77 | C
Elvin | 68 | D
Mechanics dersinin puanları harf notlarıyla.

Basit CASE ve CASE ile sıralama

Bir sütun birkaç belirli değerle karşılaştırılırken kısa bir biçim vardır: CASE sütun WHEN değer THEN ... END. Bu, = ile yapılan denetimlerin kısaltmasıdır. CASE, ORDER BY içinde de yazılabilir: aşağıda müşterileri para birimleriyle gösteriyor, Azerbaycan'daki müşterileri listenin başına alıyoruz.

SQL
SELECT name, country,
       CASE country
         WHEN 'Azerbaijan'     THEN 'AZN'
         WHEN 'Türkiye'        THEN 'TRY'
         WHEN 'Russia'         THEN 'RUB'
         WHEN 'United Kingdom' THEN 'GBP'
       END AS currency
FROM customers
ORDER BY CASE WHEN country = 'Azerbaijan' THEN 0 ELSE 1 END, name;
▸ Beklenen çıktı
name | country | currency
Anar Mustafayev | Azerbaijan | AZN
Lalə Əhmədova | Azerbaijan | AZN
Zəhra Hüseynli | Azerbaijan | AZN
Emre Yılmaz | Türkiye | TRY
John Carter | United Kingdom | GBP
Mehmet Kaya | Türkiye | TRY
Olga Ivanova | Russia | RUB

COALESCE ve NULLIF

COALESCE(a, b, c) listedeki NULL olmayan ilk değeri döndürür; bu, CASE WHEN a IS NOT NULL THEN a WHEN b IS NOT NULL THEN b ELSE c END ifadesinin kısa yazımıdır. NULLIF(a, b) ise tersini yapar: a = b olduğunda NULL, aksi hâlde a döndürür. Asıl görevi sıfıra bölmeyi zararsız hâle getirmektir: x / NULLIF(y, 0) ifadesinde y sıfırsa bölme NULL ile yapılır ve sonuç NULL olur.

SQL
SELECT p.name, p.stock,
       COALESCE(SUM(o.quantity), 0) AS sold,
       ROUND(1.0 * COALESCE(SUM(o.quantity), 0) / NULLIF(p.stock, 0), 3) AS sold_per_stock
FROM products AS p
LEFT JOIN orders AS o ON o.product_id = p.id
WHERE p.category = 'Electronics'
GROUP BY p.id, p.name, p.stock
ORDER BY p.id;
▸ Beklenen çıktı
name | stock | sold | sold_per_stock
Laptop | 8 | 1 | 0.125
Smartphone | 15 | 2 | 0.133
Headphones | 40 | 3 | 0.075
Monitor | 0 | 0 | NULL
Stokta olmayan Monitor için bölme hata değil, NULL verir.

Koşullu toplama ve pivot

CASE bir toplama fonksiyonunun içine yazıldığında çok güçlü bir araca dönüşür. SUM(CASE WHEN koşul THEN 1 ELSE 0 END) koşulu sağlayan satırları sayar. Böyle birkaç sütun yazarsak satırlardaki değerler sütunlara dönüşür; tıpkı Excel'deki pivot tablo gibi. Aşağıda her şehir için sınıflara göre öğrenci sayısını görüyoruz.

SQL
SELECT city,
       SUM(CASE WHEN grade = 8  THEN 1 ELSE 0 END) AS g8,
       SUM(CASE WHEN grade = 9  THEN 1 ELSE 0 END) AS g9,
       SUM(CASE WHEN grade = 10 THEN 1 ELSE 0 END) AS g10,
       SUM(CASE WHEN grade = 11 THEN 1 ELSE 0 END) AS g11,
       COUNT(*) AS total
FROM students
GROUP BY city
ORDER BY total DESC, city;
▸ Beklenen çıktı
city | g8 | g9 | g10 | g11 | total
Bakı | 1 | 2 | 1 | 0 | 4
Gəncə | 0 | 0 | 1 | 1 | 2
Sumqayıt | 1 | 0 | 0 | 1 | 2
Lənkəran | 1 | 0 | 0 | 0 | 1
Naxçıvan | 0 | 0 | 0 | 1 | 1
Quba | 0 | 0 | 1 | 0 | 1
Şəki | 0 | 1 | 0 | 0 | 1

Aynı yöntemle paylar da hesaplanır: 0 ve 1'lerin ortalaması, koşulu sağlayan satırların payıdır. COUNT(CASE WHEN koşul THEN 1 END) de çalışır; çünkü ELSE yoksa değer NULL olur, COUNT ise NULL değerleri saymaz.

SQL
SELECT c.title,
       COUNT(*) AS students,
       COUNT(CASE WHEN e.score >= 90 THEN 1 END) AS excellent,
       ROUND(100.0 * AVG(CASE WHEN e.score >= 90 THEN 1 ELSE 0 END), 1) AS excellent_pct
FROM enrollments AS e
JOIN courses AS c ON c.id = e.course_id
GROUP BY c.id, c.title
ORDER BY excellent_pct DESC, c.title;
▸ Beklenen çıktı
title | students | excellent | excellent_pct
Python Basics | 3 | 2 | 66.7
Algebra | 4 | 2 | 50
English B1 | 2 | 1 | 50
World History | 2 | 1 | 50
Geometry | 3 | 1 | 33.3
Mechanics | 4 | 1 | 25
Organic Chemistry | 2 | 0 | 0
İşlemSQLitePostgreSQLMySQLSQL Server
Kısa ifIIF(c, a, b)CASEIF(c, a, b)IIF(c, a, b)
Koşullu saymaCOUNT(*) FILTER (WHERE c)COUNT(*) FILTER (WHERE c)SUM(c)SUM(CASE ...)
Hazır pivotyokcrosstab (tablefunc eklentisi)yokPIVOT
CASE ise her VTYS'de aynı çalışır; taşınabilir sorgular için onu seç. MySQL'de karşılaştırma 1 ya da 0 döndürdüğü için SUM(score >= 90) de sayar.
Alıştırma

Her ürün için adı, stoğu (stock) ve durumu (status) göster: stok 0 ise 'out of stock', 20'den azsa 'low', diğer durumlarda 'ok'. Sonucu stoğa, sonra ada göre sırala.

Alıştırma · SQL
SELECT name, stock
       -- add the status column with CASE
FROM products
ORDER BY stock, name;
▸ Beklenen çıktı
name | stock | status
Monitor | 0 | out of stock
Laptop | 8 | low
Smartphone | 15 | low
Chess set | 18 | low
Desk lamp | 25 | ok
Headphones | 40 | ok
Backpack | 60 | ok
Water bottle | 120 | ok
Pen set | 300 | ok
Notebook | 500 | ok
Alıştırma

Bir pivot rapor kur: her ülke (country) için sipariş edilen Electronics ürünlerinin toplam adedini (electronics) ve diğer kategorilerin toplam adedini (other) göster. Sonucu ülkeye göre sırala.

Alıştırma · SQL
SELECT c.country
       -- electronics and other
FROM orders AS o
JOIN customers AS c ON c.id = o.customer_id
JOIN products  AS p ON p.id = o.product_id
GROUP BY c.country
ORDER BY c.country;
▸ Beklenen çıktı
country | electronics | other
Azerbaijan | 5 | 33
Russia | 0 | 1
Türkiye | 1 | 5
United Kingdom | 0 | 2

Önemli noktalar

  • CASE WHEN ... THEN ... ELSE ... END ilk doğru koşulun değerini döndürür; ELSE yoksa NULL elde edilir.
  • Koşulları en darından en genişine doğru yaz; CASE, SELECT, ORDER BY, WHERE içinde ve toplama fonksiyonlarının içinde çalışır.
  • COALESCE NULL olmayan ilk değeri verir, NULLIF(y, 0) ise sıfıra bölmeden korur.
  • SUM(CASE WHEN koşul THEN 1 ELSE 0 END) sayar, AVG(...) ise pay verir; pivot raporların temeli budur.

Kendini test et

10 soru. Her doğru cevap XP kazandırır.

1 / 10
CASE WHEN score >= 90 THEN 'A' WHEN score >= 80 THEN 'B' WHEN score >= 70 THEN 'C' ELSE 'D' END ifadesi 85 puan için ne döndürür?