Skip to content

Temel SQL Komutları

Bu dersi tamamladıktan sonra:

  • Temel SQL komutlarını (SELECT, INSERT, UPDATE, DELETE) kullanabileceksiniz
  • JOIN çeşitlerini ve ne zaman kullanılacağını öğreneceksiniz
  • Aggregation fonksiyonlarını kullanabileceksiniz
  • Subquery’ler ve CTE’ler oluşturabileceksiniz
  1. SELECT - Veri Okuma
  2. INSERT - Veri Ekleme
  3. UPDATE - Veri Güncelleme
  4. DELETE - Veri Silme
  5. JOIN - Tablo Birleştirme
  6. Aggregation Fonksiyonları
  7. Subquery’ler ve CTE’ler

-- Tüm sütunları seç
SELECT * FROM users;
-- Belirli sütunları seç
SELECT username, email, first_name FROM users;
-- Sütunları yeniden adlandırma
SELECT username AS kullanici_adi, email AS eposta FROM users;
-- Eşitlik
SELECT * FROM users WHERE username = 'ahmet';
-- Karşılaştırma operatörleri
SELECT * FROM users WHERE id > 5;
SELECT * FROM posts WHERE published = 1;
-- Mantıksal operatörler
SELECT * FROM users WHERE username = 'ahmet' AND email = '[email protected]';
SELECT * FROM posts WHERE published = 1 OR user_id = 2;
-- BETWEEN
SELECT * FROM posts WHERE created_at BETWEEN '2024-01-01' AND '2024-12-31';
-- IN
SELECT * FROM users WHERE username IN ('ahmet', 'ayse', 'mehmet');
-- NOT
SELECT * FROM users WHERE username NOT IN ('test', 'demo');
-- Pattern matching (LIKE)
SELECT * FROM users WHERE email LIKE '%@example.com';
SELECT * FROM users WHERE username LIKE 'a%'; -- 'a' ile başlayanlar
SELECT * FROM users WHERE username LIKE '%m'; -- 'm' ile bitenler
-- IS NULL
SELECT * FROM users WHERE last_name IS NULL;
-- Artan sıralama
SELECT * FROM users ORDER BY username ASC;
-- Azalan sıralama
SELECT * FROM users ORDER BY created_at DESC;
-- Çoklu sıralama
SELECT * FROM posts ORDER BY published DESC, created_at ASC;
-- İlk 5 kayıt
SELECT * FROM users LIMIT 5;
-- 5. kayıttan sonraki 10 kayıt
SELECT * FROM users LIMIT 10 OFFSET 5;
-- Sayfalama (page size: 10, page: 2)
SELECT * FROM posts LIMIT 10 OFFSET 10;
-- Benzersiz kullanıcılar
SELECT DISTINCT user_id FROM posts;
-- Benzersiz kombinasyonlar
SELECT DISTINCT user_id, published FROM posts;

-- Tüm sütunlar için
INSERT INTO users (email, username, first_name, last_name)
VALUES ('[email protected]', 'newuser', 'New', 'User');
-- ID belirterek
INSERT INTO users (id, email, username, first_name, last_name)
VALUES (100, '[email protected]', 'newuser', 'New', 'User');
INSERT INTO users (email, username, first_name, last_name)
VALUES
('[email protected]', 'user1', 'User', 'One'),
('[email protected]', 'user2', 'User', 'Two'),
('[email protected]', 'user3', 'User', 'Three');
-- Başka bir tablodan veri ekleme
INSERT INTO archived_users (email, username, first_name, last_name)
SELECT email, username, first_name, last_name
FROM users
WHERE created_at < '2023-01-01';

-- Tek sütunu güncelle
UPDATE users SET first_name = 'Ahmet Can' WHERE username = 'ahmet';
-- Çoklu sütun güncelleme
UPDATE users
SET first_name = 'Ahmet Can',
last_name = 'Yılmaz',
updated_at = CURRENT_TIMESTAMP
WHERE username = 'ahmet';
-- Belirli bir koşula göre güncelle
UPDATE posts SET published = 1 WHERE published = 0 AND created_at > '2024-01-01';
-- Subquery ile güncelleme
UPDATE users
SET last_name = 'Updated'
WHERE id IN (SELECT user_id FROM posts WHERE published = 1);

-- Belirli bir kaydı sil
DELETE FROM users WHERE username = 'testuser';
-- Koşula göre silme
DELETE FROM posts WHERE published = 0 AND created_at < '2024-01-01';
-- Tüm kayıtları sil (tabloyu korur)
DELETE FROM posts;
-- Tabloyu tamamen sil
DROP TABLE posts;

Sadece eşleşen kayıtları getirir:

-- Kullanıcıları ve post'larını getir
SELECT users.username, posts.title
FROM posts
INNER JOIN users ON posts.user_id = users.id;
-- Kısa yazımı (JOIN)
SELECT users.username, posts.title
FROM posts
JOIN users ON posts.user_id = users.id;

Sol tablodaki tüm kayıtları ve sağ tablodan eşleşenleri getirir:

-- Tüm kullanıcıları ve varsa post'larını getir
SELECT users.username, posts.title
FROM users
LEFT JOIN posts ON users.id = posts.user_id;
-- Post'u olmayan kullanıcıları bul
SELECT users.username
FROM users
LEFT JOIN posts ON users.id = posts.user_id
WHERE posts.id IS NULL;

Sağ tablodaki tüm kayıtları ve sol tablodan eşleşenleri getirir:

SELECT users.username, posts.title
FROM users
RIGHT JOIN posts ON users.id = posts.user_id;

SQLite’da doğrudan desteklenmez, UNION ile simüle edilebilir:

SELECT users.username, posts.title
FROM users
LEFT JOIN posts ON users.id = posts.user_id
UNION
SELECT users.username, posts.title
FROM users
RIGHT JOIN posts ON users.id = posts.user_id;

Aynı tabloyu kendisiyle birleştirme:

-- Kullanıcıları takip edenleri bul
SELECT
u1.username AS user,
u2.username AS following
FROM follows f
JOIN users u1 ON f.follower_id = u1.id
JOIN users u2 ON f.following_id = u2.id;

-- Toplam kayıt sayısı
SELECT COUNT(*) FROM users;
-- Belirli bir koşula göre sayma
SELECT COUNT(*) FROM posts WHERE published = 1;
-- Benzersiz kayıt sayısı
SELECT COUNT(DISTINCT user_id) FROM posts;
-- Toplam değer
SELECT SUM(view_count) FROM posts;
-- Grup bazlı toplam
SELECT user_id, SUM(view_count) as total_views
FROM posts
GROUP BY user_id;
-- Ortalama
SELECT AVG(view_count) FROM posts;
-- Grup bazlı ortalama
SELECT user_id, AVG(view_count) as avg_views
FROM posts
GROUP BY user_id;
-- Minimum değer
SELECT MIN(created_at) FROM posts;
-- Maksimum değer
SELECT MAX(view_count) FROM posts;
-- Her kullanıcının en çok görüntülenen post'u
SELECT user_id, MAX(view_count) as max_views
FROM posts
GROUP BY user_id;
-- Her kullanıcının post sayısı
SELECT user_id, COUNT(*) as post_count
FROM posts
GROUP BY user_id;
-- Çoklu gruplama
SELECT user_id, published, COUNT(*) as count
FROM posts
GROUP BY user_id, published;

Gruplama sonrası filtreleme:

-- Post sayısı 5'ten fazla olan kullanıcılar
SELECT user_id, COUNT(*) as post_count
FROM posts
GROUP BY user_id
HAVING COUNT(*) > 5;
-- Ortalama görüntülenme 100'den fazla olan kullanıcılar
SELECT user_id, AVG(view_count) as avg_views
FROM posts
GROUP BY user_id
HAVING AVG(view_count) > 100;

Tek bir değer döndüren subquery:

-- En çok post'a sahip kullanıcı
SELECT username, first_name, last_name
FROM users
WHERE id = (
SELECT user_id
FROM posts
GROUP BY user_id
ORDER BY COUNT(*) DESC
LIMIT 1
);

Tek bir satır döndüren subquery:

-- Kullanıcı bilgisi ve post sayısı
SELECT u.*,
(
SELECT COUNT(*)
FROM posts
WHERE user_id = u.id
) as post_count
FROM users u;
-- Post'u olan kullanıcılar
SELECT * FROM users
WHERE id IN (SELECT DISTINCT user_id FROM posts);
-- Post'u olmayan kullanıcılar
SELECT * FROM users
WHERE id NOT IN (SELECT DISTINCT user_id FROM posts);
-- Post'u olan kullanıcılar (daha performanslı)
SELECT * FROM users u
WHERE EXISTS (
SELECT 1 FROM posts p WHERE p.user_id = u.id
);
-- Post'u olmayan kullanıcılar
SELECT * FROM users u
WHERE NOT EXISTS (
SELECT 1 FROM posts p WHERE p.user_id = u.id
);

Geçici tablo oluşturma:

-- Kullanıcı post sayıları
WITH user_post_counts AS (
SELECT
user_id,
COUNT(*) as post_count
FROM posts
GROUP BY user_id
)
SELECT
u.username,
u.email,
COALESCE(upc.post_count, 0) as post_count
FROM users u
LEFT JOIN user_post_counts upc ON u.id = upc.user_id
ORDER BY post_count DESC;
-- Karmaşık CTE örneği
WITH active_users AS (
SELECT DISTINCT user_id
FROM posts
WHERE created_at > DATE('now', '-30 days')
),
top_posters AS (
SELECT
user_id,
COUNT(*) as post_count
FROM posts
WHERE user_id IN (SELECT user_id FROM active_users)
GROUP BY user_id
ORDER BY post_count DESC
LIMIT 10
)
SELECT
u.username,
u.email,
tp.post_count
FROM top_posters tp
JOIN users u ON tp.user_id = u.id;

-- Her post'un kullanıcı içindeki sıralaması
SELECT
title,
user_id,
view_count,
RANK() OVER (PARTITION BY user_id ORDER BY view_count DESC) as rank
FROM posts;
-- Running total
SELECT
created_at,
view_count,
SUM(view_count) OVER (ORDER BY created_at) as running_total
FROM posts;
-- Koşullu değerlendirme
SELECT
title,
view_count,
CASE
WHEN view_count > 1000 THEN 'Very Popular'
WHEN view_count > 100 THEN 'Popular'
WHEN view_count > 10 THEN 'Normal'
ELSE 'Low'
END as popularity_level
FROM posts;
-- İki sorguyu birleştir (tekrarlayanları ele)
SELECT username FROM users
WHERE id < 5
UNION
SELECT username FROM users
WHERE id > 10;
-- İki sorguyu birleştir (tüm kayıtlar)
SELECT username FROM users
WHERE id < 5
UNION ALL
SELECT username FROM users
WHERE id > 10;

-- Temel metrikler
SELECT
(SELECT COUNT(*) FROM users) as total_users,
(SELECT COUNT(*) FROM posts) as total_posts,
(SELECT COUNT(*) FROM posts WHERE published = 1) as published_posts,
(SELECT COUNT(*) FROM posts WHERE created_at > DATE('now', '-7 days')) as posts_this_week;
-- En aktif yazarlar
SELECT
u.username,
COUNT(p.id) as post_count,
SUM(p.view_count) as total_views
FROM users u
JOIN posts p ON u.id = p.user_id
WHERE p.created_at > DATE('now', '-30 days')
GROUP BY u.id
ORDER BY post_count DESC
LIMIT 10;
-- Popüler içerikler
SELECT
p.title,
u.username as author,
p.view_count,
p.created_at
FROM posts p
JOIN users u ON p.user_id = u.id
WHERE p.published = 1
ORDER BY p.view_count DESC
LIMIT 20;
-- Kullanıcı etkileşim özeti
WITH user_stats AS (
SELECT
u.id,
u.username,
COUNT(DISTINCT p.id) as post_count,
COALESCE(SUM(p.view_count), 0) as total_views
FROM users u
LEFT JOIN posts p ON u.id = p.user_id
GROUP BY u.id
)
SELECT
username,
post_count,
total_views,
CASE
WHEN post_count = 0 THEN 'Inactive'
WHEN post_count < 5 THEN 'Occasional'
WHEN post_count < 20 THEN 'Active'
ELSE 'Power User'
END as engagement_level
FROM user_stats
ORDER BY total_views DESC;

-- ✅ Index'li sütunları WHERE'ta kullanın
SELECT * FROM users WHERE email = '[email protected]';
-- ✅ SELECT * yerine gerekli sütunları seçin
SELECT username, email FROM users;
-- ✅ LIMIT kullanın
SELECT * FROM posts LIMIT 100;
-- ✅ EXISTS yerine IN kullanın (bazı durumlarda)
SELECT * FROM users WHERE id IN (SELECT user_id FROM posts);
-- ✅ CTE kullanın (okunabilirlik için)
WITH active_users AS (
SELECT DISTINCT user_id FROM posts WHERE created_at > DATE('now', '-7 days')
)
SELECT * FROM users WHERE id IN (SELECT user_id FROM active_users);
-- ❌ Leading wildcard kullanın (index kullanılmaz)
SELECT * FROM users WHERE email LIKE '%@example.com';
-- ❌ SELECT * kullanın (gereksiz veri transferi)
SELECT * FROM users WHERE id = 1;
-- ❌ Funksiyonları index'li sütunlarda WHERE'ta kullanın
SELECT * FROM users WHERE LOWER(username) = 'ahmet';
-- ❌ N+1 query problemi
-- (Her kullanıcı için ayrı sorgu)
-- Bunun yerine JOIN kullanın

Bu derste aşağıdaki konuları öğrendiniz:

✅ SELECT komutu ve filtreleme teknikleri ✅ INSERT, UPDATE, DELETE komutları ✅ JOIN çeşitleri ve kullanım alanları ✅ Aggregation fonksiyonları (COUNT, SUM, AVG, MIN, MAX) ✅ GROUP BY ve HAVING kullanımı ✅ Subquery’ler ve CTE’ler ✅ Performans optimizasyon teknikleri

Bir sonraki dersimizde “Wrangler ile D1 Kullanımı” başlığı altında:

  • Wrangler CLI komutları
  • Migration yönetimi
  • Local vs Remote development
  • Best practices konularını inceleyeceğiz.
  1. INNER JOIN ve LEFT JOIN arasındaki fark nedir?
  2. HAVING ve WHERE arasındaki fark nedir?
  3. Subquery ve CTE arasında hangi durumda hangisini kullanmalısınız?
  4. SELECT * neden önerilmez?
  5. Performansı artırmak için hangi index stratejilerini kullanabilirsiniz?

Ders Süresi: 75 dakika Zorluk Seviyesi: Orta Ön Koşullar: Ders 3: İlk Veritabanını Oluşturma