← Kursa Dön
📄 Text · 35 min

SELECT, FROM, WHERE Temelleri

Giriş — Veritabanına Soru Sormak

Buraya kadar veritabanı oluşturduk, tablolar tanımladık, veri ekledik, güncelledik, sildik. Ama bir veritabanının asıl gücü sorgulama yeteneğindedir. "İstanbul'daki müşteriler kim?", "Bu ay kaç sipariş verildi?", "En pahalı ürün hangisi?" — bu soruların cevabını SELECT komutuyla alırsın.

SELECT, SQL'de en çok kullanılan komuttur. Bir geliştirici olarak günlük iş akışının büyük çoğunluğu SELECT sorguları yazmaktır. Bu derste SELECT'in temellerini, FROM ile tablo seçmeyi ve WHERE ile filtrelemeyi öğreneceğiz.

🎯 Analoji: Google'da arama yapmayı düşün. Arama kutusuna ne istediğini yazarsın, Google hangi sayfalarda arayacağını bilir ve sonuçları filtreler. SELECT → ne istediğin, FROM → nerede arayacağın, WHERE → filtreleme kriterlerin.


SELECT — Ne İstiyorsun?

Tüm Sütunları Getir (SELECT *)

-- customers tablosundaki TÜM sütunları ve TÜM satırları getir
SELECT * FROM customers;

* (yıldız / asterisk) "tüm sütunlar" anlamına gelir. Sonuç:

+-------------+------------+-----------+-------------------+-------------+----------+-------------------+-----------+
| customer_id | first_name | last_name | email             | phone       | city     | registration_date | is_active |
+-------------+------------+-----------+-------------------+-------------+----------+-------------------+-----------+
| 1           | Ahmet      | Yılmaz    | ahmet@email.com   | 05551001001 | İstanbul | 2024-01-15        | 1         |
| 2           | Zeynep     | Kaya      | zeynep@email.com  | 05551001002 | Ankara   | 2024-01-15        | 1         |
| 3           | Mehmet     | Demir     | mehmet@email.com  | 05551001003 | İzmir    | 2024-01-15        | 1         |
| ...         | ...        | ...       | ...               | ...         | ...      | ...               | ...       |
+-------------+------------+-----------+-------------------+-------------+----------+-------------------+-----------+

⚠️ Dikkat: Production'da SELECT * kullanmaktan kaçın. Nedenleri: - Gereksiz sütunları çeker → daha fazla ağ trafiği, bellek kullanımı - Tabloya sütun eklendiğinde uygulamanın davranışı değişebilir - Index kullanımını engelleyebilir (covering index çalışmaz) - Kodu okuyan kişi hangi sütunların kullanıldığını anlamaz Hızlı kontrol ve geliştirme ortamında sorun yok ama production sorgularında sütunları açıkça yaz.

Belirli Sütunları Getir

-- Sadece isim ve e-posta bilgisini getir
SELECT first_name, last_name, email 
FROM customers;
+------------+-----------+-------------------+
| first_name | last_name | email             |
+------------+-----------+-------------------+
| Ahmet      | Yılmaz    | ahmet@email.com   |
| Zeynep     | Kaya      | zeynep@email.com  |
| Mehmet     | Demir     | mehmet@email.com  |
| ...        | ...       | ...               |
+------------+-----------+-------------------+

Hesaplamalı Sütunlar

SELECT'te sütun adları yanında hesaplama da yapabilirsin:

-- Ürün adı ve KDV dahil fiyat (fiyat * 1.20)
SELECT product_name, 
       price, 
       price * 1.20 AS price_with_vat
FROM products;
+-------------------+----------+----------------+
| product_name      | price    | price_with_vat |
+-------------------+----------+----------------+
| MacBook Pro 14"   | 54999.99 | 65999.99       |
| iPhone 15 Pro     | 64999.99 | 77999.99       |
| Kablosuz Mouse    | 299.99   | 359.99         |
| ...               | ...      | ...            |
+-------------------+----------+----------------+

Sabit Değer ve İfadeler

-- Sabit değer döndürme
SELECT 'Merhaba Dünya' AS mesaj;
-- Sonuç: "Merhaba Dünya"

-- Hesaplama
SELECT 2 + 3 AS toplam, 10 * 5 AS carpim, 100 / 3 AS bolum;
-- toplam: 5, carpim: 50, bolum: 33.3333

-- Fonksiyon
SELECT NOW() AS simdi, CURDATE() AS bugun, VERSION() AS mysql_version;

-- String birleştirme
SELECT CONCAT(first_name, ' ', last_name) AS full_name
FROM customers;

FROM — Nerede Arayacaksın?

FROM hangi tablodan veri çekileceğini belirtir:

-- Tek tablodan
SELECT * FROM products;

-- İleride göreceğimiz: birden fazla tablodan (JOIN)
SELECT c.first_name, o.total_amount
FROM customers c
JOIN orders o ON c.customer_id = o.customer_id;

Tablo Alias'ı

Tablo isimlerine kısa ad (alias) verebilirsin:

-- Alias olmadan (uzun ve tekrarlı)
SELECT customers.first_name, customers.last_name 
FROM customers;

-- Alias ile (kısa ve okunabilir)
SELECT c.first_name, c.last_name 
FROM customers c;

-- veya AS keyword'ü ile (aynı şey)
SELECT c.first_name, c.last_name 
FROM customers AS c;

Alias'lar özellikle JOIN'lerde birden fazla tablo kullanıldığında çok işe yarar. Tek tabloda opsiyoneldir ama birden fazla tabloda neredeyse zorunludur.


WHERE — Filtreleme

WHERE, döndürülen satırları koşula göre filtreler. Koşula uyan satırlar döner, uymayanlar dönemez.

Temel Karşılaştırma

-- Belirli bir müşteri
SELECT * FROM customers WHERE customer_id = 1;

-- Belirli bir şehir
SELECT first_name, last_name, city 
FROM customers 
WHERE city = 'İstanbul';

-- Belirli bir fiyatın üstündeki ürünler
SELECT product_name, price 
FROM products 
WHERE price > 10000;

-- Belirli bir duruma sahip siparişler
SELECT order_id, customer_id, status 
FROM orders 
WHERE status = 'pending';

Karşılaştırma Operatörleri

OperatörAnlamıÖrnek
=EşitWHERE city = 'İstanbul'
!= veya <>Eşit değilWHERE status != 'cancelled'
>BüyükWHERE price > 1000
<KüçükWHERE stock_quantity < 10
>=Büyük veya eşitWHERE price >= 500
<=Küçük veya eşitWHERE age <= 30
-- Fiyatı 1000 TL ve üstü olan ürünler
SELECT product_name, price 
FROM products 
WHERE price >= 1000;

-- İptal edilmemiş siparişler
SELECT order_id, status, total_amount 
FROM orders 
WHERE status <> 'cancelled';
-- veya
SELECT order_id, status, total_amount 
FROM orders 
WHERE status != 'cancelled';

💡 İpucu: != ve <> aynı şeyi yapar. <> SQL standardıdır, != daha yaygın kullanılır. İkisi de sorunsuz çalışır, hangisini tercih edersen et ama projede tutarlı ol.


Mantık Operatörleri: AND, OR, NOT

AND — Her İki Koşul da Sağlanmalı

-- İstanbul'daki VE aktif müşteriler
SELECT first_name, last_name, city, is_active 
FROM customers 
WHERE city = 'İstanbul' AND is_active = TRUE;

-- Fiyatı 1000-5000 arası olan aktif ürünler
SELECT product_name, price, is_active 
FROM products 
WHERE price >= 1000 AND price <= 5000 AND is_active = TRUE;

OR — Koşullardan Biri Sağlanmalı

-- İstanbul VEYA Ankara'daki müşteriler
SELECT first_name, last_name, city 
FROM customers 
WHERE city = 'İstanbul' OR city = 'Ankara';

-- Teslim edilmiş VEYA kargodaki siparişler
SELECT order_id, status 
FROM orders 
WHERE status = 'delivered' OR status = 'shipped';

NOT — Koşulun Tersi

-- İstanbul'da OLMAYAN müşteriler
SELECT first_name, last_name, city 
FROM customers 
WHERE NOT city = 'İstanbul';
-- veya
SELECT first_name, last_name, city 
FROM customers 
WHERE city != 'İstanbul';

-- İptal edilmemiş siparişler
SELECT * FROM orders WHERE NOT status = 'cancelled';

AND ve OR'u Birlikte Kullanma — Parantez Önemi

-- ⚠️ Parantez olmadan — beklenmedik sonuç!
SELECT * FROM products 
WHERE category_id = 1 OR category_id = 2 AND price > 10000;
-- Bu, AND önce değerlendirilir:
-- category_id = 1 OR (category_id = 2 AND price > 10000)
-- Yani: Tüm Elektronik ürünler + 10000 üstü Bilgisayarlar

-- ✅ Parantez ile — istenilen sonuç
SELECT * FROM products 
WHERE (category_id = 1 OR category_id = 2) AND price > 10000;
-- Önce OR değerlendirilir, sonra AND:
-- Elektronik veya Bilgisayar kategorisindeki VE 10000 üstü ürünler

⚠️ Dikkat: SQL'de operatör önceliği: NOT > AND > OR. Bu, matematikte çarpmanın toplamadan önce gelmesi gibidir. Karışıklığı önlemek için parantez kullan — hem doğru çalışır hem okunabilir olur.


Sık Kullanılan WHERE Pattern'ları

IN — Birden Fazla Değer Kontrolü

-- OR yerine IN kullan (daha okunabilir)
-- Yerine:
SELECT * FROM customers 
WHERE city = 'İstanbul' OR city = 'Ankara' OR city = 'İzmir';

-- IN ile:
SELECT * FROM customers 
WHERE city IN ('İstanbul', 'Ankara', 'İzmir');

-- Sipariş durumu filtresi
SELECT * FROM orders 
WHERE status IN ('pending', 'processing');

NOT IN — Hariç Tutma

-- İstanbul ve Ankara dışındaki müşteriler
SELECT * FROM customers 
WHERE city NOT IN ('İstanbul', 'Ankara');

BETWEEN — Aralık Kontrolü

-- Fiyatı 1000 ile 5000 arasındaki ürünler (sınırlar dahil)
SELECT product_name, price 
FROM products 
WHERE price BETWEEN 1000 AND 5000;
-- Bu şuna eşdeğer: price >= 1000 AND price <= 5000

-- Tarih aralığı
SELECT order_id, order_date, total_amount 
FROM orders 
WHERE order_date BETWEEN '2024-01-01' AND '2024-01-31';

LIKE — Metin Arama (Pattern Matching)

-- İsmi "A" ile başlayan müşteriler
SELECT * FROM customers WHERE first_name LIKE 'A%';
-- % = sıfır veya daha fazla herhangi bir karakter

-- E-postası "email.com" ile biten müşteriler
SELECT * FROM customers WHERE email LIKE '%email.com';

-- İsmi "me" içeren müşteriler
SELECT * FROM customers WHERE first_name LIKE '%me%';

-- İsmi tam 5 karakter olan müşteriler
SELECT * FROM customers WHERE first_name LIKE '_____';
-- _ = tam olarak bir karakter

-- İsmi "A" ile başlayan ve 5 karakter olan
SELECT * FROM customers WHERE first_name LIKE 'A____';

LIKE wildcard'ları:

  • % → Sıfır veya daha fazla herhangi bir karakter

  • _ → Tam olarak bir karakter

-- Ürün adında "Pro" geçen ürünler
SELECT product_name, price 
FROM products 
WHERE product_name LIKE '%Pro%';
-- MacBook Pro 14", iPhone 15 Pro

💡 İpucu: LIKE case-insensitive'dir (collation'a bağlı). utf8mb4_unicode_ci ile 'ahmet' LIKE 'AHMET' eşleşir. Case-sensitive arama için LIKE BINARY kullan veya collation'ı _bin olarak ayarla.


WHERE Koşullarının Değerlendirme Sırası

SQL sorgusu yazarken şu mantıksal sırayı hatırla:

SELECT sütunlar        -- 3. Son: hangi sütunları göster
FROM tablo             -- 1. İlk: hangi tablodan al
WHERE koşul;           -- 2. Sonra: hangi satırları filtrele

Veritabanı motoru:

  1. FROM → Tabloyu belirler

  2. WHERE → Satırları filtreler

  3. SELECT → Sütunları seçer ve döndürür

Bu sıra önemlidir çünkü SELECT'te tanımlanan alias'ı WHERE'de kullanamazsın:

-- ❌ HATA — WHERE, SELECT'ten önce çalışır
SELECT product_name, price * 1.20 AS kdv_dahil_fiyat
FROM products
WHERE kdv_dahil_fiyat > 10000;
-- ERROR: Unknown column 'kdv_dahil_fiyat'

-- ✅ Doğru — hesaplamayı WHERE'de tekrar yaz
SELECT product_name, price * 1.20 AS kdv_dahil_fiyat
FROM products
WHERE price * 1.20 > 10000;

Gerçek Dünya Örneği — E-Ticaret Raporları

-- 1. İstanbul'daki aktif müşterilerin isim ve e-postaları
SELECT first_name, last_name, email
FROM customers
WHERE city = 'İstanbul' AND is_active = TRUE;

-- 2. 10.000 TL üstü, stokta olan ürünler
SELECT product_name, price, stock_quantity
FROM products
WHERE price > 10000 AND stock_quantity > 0 AND is_active = TRUE;

-- 3. Ocak 2024'teki tamamlanmış siparişler
SELECT order_id, customer_id, order_date, total_amount
FROM orders
WHERE order_date BETWEEN '2024-01-01' AND '2024-01-31 23:59:59'
  AND status = 'delivered';

-- 4. Elektronik kategorisindeki (category_id: 1, 2, 3) ürünler
SELECT product_name, price, category_id
FROM products
WHERE category_id IN (1, 2, 3)
  AND price BETWEEN 100 AND 50000;

-- 5. Ürün adında "Kablosuz" veya "Bluetooth" geçen ürünler
SELECT product_name, price
FROM products
WHERE product_name LIKE '%Kablosuz%' 
   OR product_name LIKE '%Bluetooth%';

Sıkça Yapılan Hatalar

  1. String değerde tek tırnağı unutmak: WHERE city = Istanbul hata verir. String değerler tek tırnak içinde olmalı: WHERE city = 'İstanbul'.

  2. = yerine == kullanmak: Python refleksiyle WHERE id == 1 yazmak. SQL'de eşitlik tek =.

  3. AND/OR önceliğini bilmemek: A OR B AND C ifadesi A OR (B AND C) olarak değerlendirilir. Parantez kullan.

  4. SELECT alias'ını WHERE'de kullanmak: WHERE, SELECT'ten önce çalışır — alias henüz tanımlı değildir.

  5. NULL ile = karşılaştırması: WHERE phone = NULL çalışmaz! NULL karşılaştırması IS NULL ile yapılır. Bu konuyu bir sonraki derste detaylıca işleyeceğiz.

  6. LIKE'ta % kullanmamak: WHERE name LIKE 'Ahmet' sadece tam eşleşmeyi bulur (LIKE yerine = kullansan aynı). İçeriyor araması için LIKE '%Ahmet%' yaz.


Özet

  • SELECT sütunlar FROM tablo WHERE koşul — temel sorgulama yapısı

  • SELECT * tüm sütunları getirir ama production'da belirli sütunları yaz

  • WHERE satırları filtreler — koşula uyanlar döner

  • Karşılaştırma operatörleri: =, !=/<>, >, <, >=, <=

  • Mantık operatörleri: AND (ve), OR (veya), NOT (değil)

  • IN birden fazla değer kontrolü, BETWEEN aralık kontrolü, LIKE metin arama

  • Operatör önceliği: NOT > AND > OR — karışıklığı önlemek için parantez kullan

  • SQL değerlendirme sırası: FROM → WHERE → SELECT

  • SELECT alias'ı WHERE'de kullanılamaz