DISTINCT ve Alias (AS)
Giriş — Tekrar Edenler ve Okunabilirlik
İki temel konuyu bu derste ele alacağız: DISTINCT ile tekrar eden sonuçları elemek ve AS ile sütunlara/tablolara anlamlı isimler vermek. Her ikisi de günlük SQL yazımında sürekli karşına çıkacak.
🎯 Analoji: Bir sınıfta "Hangi şehirlerden öğrencilerimiz var?" diye soruyorsun. Yoklama listesinde İstanbul 15 kez, Ankara 8 kez, İzmir 5 kez geçiyor. Ama sen her şehri bir kez duymak istiyorsun: "İstanbul, Ankara, İzmir." İşte DISTINCT tam bunu yapar — tekrarları eler, her değeri bir kez gösterir.
DISTINCT — Tekrar Eden Satırları Eleme
Temel Kullanım
-- Müşterilerimiz hangi şehirlerden?
SELECT city FROM customers;
-- İstanbul, Ankara, İzmir, İstanbul, Bursa, Antalya, İstanbul, Ankara, İzmir, İstanbul
-- 10 satır, birçok tekrar
-- Tekrarları ele: Her şehir bir kez
SELECT DISTINCT city FROM customers;
-- İstanbul, Ankara, İzmir, Bursa, Antalya
-- 5 satır, benzersiz değerlerBirden Fazla Sütunla DISTINCT
DISTINCT, satır bazında benzersizlik sağlar. Birden fazla sütun belirtildiğinde, sütunların kombinasyonu benzersiz olur:
-- Her müşteri-şehir kombinasyonu
SELECT DISTINCT city, is_active FROM customers;
-- İstanbul, 1
-- Ankara, 1
-- İzmir, 1
-- Bursa, 0
-- Antalya, 0
-- İstanbul, 0 (varsa)-- Sipariş verilen benzersiz müşteri-ürün çiftleri
SELECT DISTINCT oi.product_id, o.customer_id
FROM order_items oi
JOIN orders o ON oi.order_id = o.order_id;
-- Her müşterinin hangi ürünleri aldığı (tekrarsız)DISTINCT ve NULL
-- NULL değerler DISTINCT'te TEK BİR NULL olarak ele alınır
SELECT DISTINCT phone FROM customers;
-- 05551001001
-- 05551001002
-- ...
-- NULL (tüm NULL'lar tek satırda gösterilir)DISTINCT ve ORDER BY
-- Benzersiz şehirler, alfabetik sıralı
SELECT DISTINCT city
FROM customers
ORDER BY city ASC;
-- Benzersiz kategorilerin fiyat aralıkları
SELECT DISTINCT category_id
FROM products
WHERE price > 1000
ORDER BY category_id;COUNT(DISTINCT ...) — Benzersiz Değerleri Say
-- Kaç farklı şehirden müşterimiz var?
SELECT COUNT(DISTINCT city) AS unique_cities FROM customers;
-- Sonuç: 5
-- Kaç farklı müşteri sipariş vermiş?
SELECT COUNT(DISTINCT customer_id) AS unique_customers FROM orders;
-- Sonuç: 7
-- Kaç farklı ürün satılmış?
SELECT COUNT(DISTINCT product_id) AS unique_products FROM order_items;
-- Sonuç: 10DISTINCT vs GROUP BY
Her ikisi de benzersiz değerler üretebilir ama amaçları farklıdır:
-- DISTINCT — sadece benzersiz değerler
SELECT DISTINCT city FROM customers;
-- GROUP BY — benzersiz değerler + aggregate
SELECT city, COUNT(*) AS customer_count
FROM customers
GROUP BY city;| DISTINCT | GROUP BY |
|---|---|
| Tekrar eleme | Gruplama + aggregate |
| Aggregate fonksiyon gerekmiyor | Aggregate fonksiyon kullanılabilir |
| Sadece benzersiz değerleri göster | Grupla ve hesapla |
💡 İpucu: Sadece benzersiz değer listesi istiyorsan
DISTINCTyeterli. Benzersiz değerlerle birlikte sayma, toplama gibi işlem yapacaksanGROUP BYkullan.
DISTINCT Performans
-- DISTINCT, sonuçları sıralamak veya hash'lemek zorundadır — maliyet vardır
SELECT DISTINCT city FROM customers;
-- Küçük tablolarda fark etmez
-- Büyük tablolarda DISTINCT yavaşlayabilir
SELECT DISTINCT customer_email FROM million_row_table;
-- MySQL: temporary table + sort veya hash
-- Eğer sütunda index varsa DISTINCT daha hızlı çalışır
CREATE INDEX idx_city ON customers(city);
SELECT DISTINCT city FROM customers;
-- Index scan — çok daha hızlı⚠️ Dikkat:
SELECT DISTINCT *her sütunu dahil ettiği için neredeyse her satır "benzersiz" olur (primary key farklı olduğu için). Genellikle anlamsızdır ve performans israfıdır.
Alias (AS) — Sütun ve Tablo İsimlendirme
Sütun Alias'ı
-- Hesaplamalı sütuna isim ver
SELECT
product_name,
price AS normal_fiyat,
price * 0.90 AS indirimli_fiyat,
price * 1.20 AS kdv_dahil_fiyat,
stock_quantity AS stok
FROM products;AS keyword'ü opsiyoneldir — boşluk da yeterli ama AS daha okunabilir:
-- AS ile (önerilen)
SELECT first_name AS ad, last_name AS soyad FROM customers;
-- AS olmadan (çalışır ama daha az okunabilir)
SELECT first_name ad, last_name soyad FROM customers;Boşluklu Alias
-- Boşluk veya özel karakter içeren alias — tırnak kullan
SELECT
product_name AS "Ürün Adı",
price AS "Fiyat (TL)",
stock_quantity AS "Stok Durumu"
FROM products;
-- MySQL'de backtick de çalışır
SELECT
product_name AS `Ürün Adı`,
price AS `Fiyat (TL)`
FROM products;Tablo Alias'ı
-- Uzun tablo isimlerini kısalt
SELECT c.first_name, c.last_name, o.total_amount
FROM customers AS c
JOIN orders AS o ON c.customer_id = o.customer_id;
-- AS olmadan (yaygın kullanım)
SELECT c.first_name, c.last_name, o.total_amount
FROM customers c
JOIN orders o ON c.customer_id = o.customer_id;Tablo alias'ları özellikle JOIN'lerde zorunlu hale gelir — aynı sütun adı birden fazla tabloda olduğunda hangi tablodan geldiğini belirtmelisin.
Alias Kullanım Kuralları
-- ✅ ORDER BY'da alias kullanılabilir
SELECT price * 1.20 AS kdv_dahil FROM products ORDER BY kdv_dahil DESC;
-- ❌ WHERE'da alias KULLANILAMAZ (henüz tanımlı değil)
SELECT price * 1.20 AS kdv_dahil FROM products WHERE kdv_dahil > 1000;
-- ERROR! WHERE, SELECT'ten önce çalışır
-- ✅ WHERE'da hesaplamayı tekrar yaz
SELECT price * 1.20 AS kdv_dahil FROM products WHERE price * 1.20 > 1000;
-- ✅ HAVING'de alias kullanılabilir (GROUP BY sonrası)
SELECT city, COUNT(*) AS musteri_sayisi
FROM customers
GROUP BY city
HAVING musteri_sayisi > 2;CONCAT ile Ad Birleştirme — Alias'ın Gerçek Kullanımı
-- Ad ve soyadı birleştir
SELECT CONCAT(first_name, ' ', last_name) AS full_name,
email,
COALESCE(city, 'Belirtilmemiş') AS sehir
FROM customers
WHERE is_active = TRUE
ORDER BY full_name ASC;+----------------+-------------------+-------------+
| full_name | email | sehir |
+----------------+-------------------+-------------+
| Ahmet Yılmaz | ahmet@email.com | İstanbul |
| Ayşe Çelik | ayse@email.com | İstanbul |
| Can Koç | can@email.com | Ankara |
| ... | ... | ... |
+----------------+-------------------+-------------+Gerçek Dünya Örneği — Ürün Kataloğu
-- E-ticaret ürün kataloğu sorgusu
SELECT
p.product_id AS "ID",
p.product_name AS "Ürün",
COALESCE(c.category_name, 'Kategorisiz') AS "Kategori",
CONCAT('₺', FORMAT(p.price, 2)) AS "Fiyat",
CONCAT('₺', FORMAT(p.price * 0.90, 2)) AS "İndirimli Fiyat",
CASE
WHEN p.stock_quantity = 0 THEN 'Tükendi'
WHEN p.stock_quantity < 10 THEN 'Son Birkaç Adet'
ELSE 'Stokta'
END AS "Stok Durumu"
FROM products p
LEFT JOIN categories c ON p.category_id = c.category_id
WHERE p.is_active = TRUE
ORDER BY p.price DESC
LIMIT 20;ALL Keyword'ü (DISTINCT'in Tersi)
-- ALL varsayılandır — tüm satırları döndürür (tekrarlar dahil)
SELECT ALL city FROM customers;
-- = SELECT city FROM customers; (aynı şey)
-- DISTINCT — tekrarları eler
SELECT DISTINCT city FROM customers;ALL pratikte hiç kullanılmaz çünkü zaten varsayılan davranış budur. Ama varlığını bilmek iyi olur.
Sıkça Yapılan Hatalar
SELECT DISTINCT * kullanmak: Primary key her satırı benzersiz kılar, yani DISTINCT * neredeyse hiçbir şeyi elemez. Gereksiz performans maliyeti.
DISTINCT'i WHERE yerine kullanmak: Veri tekrarının sebebi kötü tablo tasarımı veya yanlış JOIN olabilir. DISTINCT'i "düzeltme bandajı" olarak kullanmak yerine sorgunun doğruluğunu kontrol et.
Alias'ı WHERE'de kullanmak: SQL değerlendirme sırasını unutma — WHERE, SELECT'ten önce çalışır.
Türkçe karakter alias'larda tırnak unutmak:
AS Ürün Adıhata verir.AS "Ürün Adı"veyaAS \Ürün Adı\`` kullan.DISTINCT ile COUNT karışıklığı:
COUNT(DISTINCT city)farklı şehir sayısını,COUNT(city)NULL olmayan şehir sayısını,COUNT(*)tüm satır sayısını verir.
Özet
DISTINCTtekrar eden satırları eler, her değeri bir kez gösterirDISTINCT satır bazında çalışır — birden fazla sütunda kombinasyon benzersizliği
COUNT(DISTINCT sütun)benzersiz değer sayısını verirDISTINCT performans maliyeti var — gereksiz yere kullanma
ASile sütun ve tablolara alias (takma ad) verilirAS keyword'ü opsiyonel ama okunabilirlik için önerilir
Alias WHERE'de kullanılamaz, ORDER BY ve HAVING'de kullanılabilir
Boşluklu alias'lar tırnak veya backtick içine yazılır
AI Asistan
Sorularını yanıtlamaya hazır