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ör | Anlamı | Örnek |
|---|---|---|
= | Eşit | WHERE city = 'İstanbul' |
!= veya <> | Eşit değil | WHERE status != 'cancelled' |
> | Büyük | WHERE price > 1000 |
< | Küçük | WHERE stock_quantity < 10 |
>= | Büyük veya eşit | WHERE price >= 500 |
<= | Küçük veya eşit | WHERE 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_ciile 'ahmet' LIKE 'AHMET' eşleşir. Case-sensitive arama içinLIKE BINARYkullan veya collation'ı_binolarak 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ı filtreleVeritabanı motoru:
FROM→ Tabloyu belirlerWHERE→ Satırları filtrelerSELECT→ 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
String değerde tek tırnağı unutmak:
WHERE city = Istanbulhata verir. String değerler tek tırnak içinde olmalı:WHERE city = 'İstanbul'.= yerine == kullanmak: Python refleksiyle
WHERE id == 1yazmak. SQL'de eşitlik tek=.AND/OR önceliğini bilmemek:
A OR B AND CifadesiA OR (B AND C)olarak değerlendirilir. Parantez kullan.SELECT alias'ını WHERE'de kullanmak: WHERE, SELECT'ten önce çalışır — alias henüz tanımlı değildir.
NULL ile = karşılaştırması:
WHERE phone = NULLçalışmaz! NULL karşılaştırmasıIS NULLile yapılır. Bu konuyu bir sonraki derste detaylıca işleyeceğiz.LIKE'ta % kullanmamak:
WHERE name LIKE 'Ahmet'sadece tam eşleşmeyi bulur (LIKE yerine = kullansan aynı). İçeriyor araması içinLIKE '%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ı yazWHEREsatırları filtreler — koşula uyanlar dönerKarşılaştırma operatörleri:
=,!=/<>,>,<,>=,<=Mantık operatörleri:
AND(ve),OR(veya),NOT(değil)INbirden fazla değer kontrolü,BETWEENaralık kontrolü,LIKEmetin aramaOperatö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
AI Asistan
Sorularını yanıtlamaya hazır