INNER JOINile ilişkili tabloları birONkoşuluna göre birleştirmekLEFT JOINile eşi olmayan satırları korumak ve bulmak- Tablo takma adlarını ve birleştirmeden sonra
GROUP BYkullanmak
enrollments tablosuna bakarsak “öğrenci 1, ders 6, puan 88” gibi sayılar görürüz. Ama insanlar “Aysel — Python Basics — 88” görmek ister. Ad students tablosunda, ders adı courses tablosunda, puan ise enrollments tablosundadır. Hepsini birlikte görmek için tabloları JOIN ile birleştirmek gerekir.
INNER JOIN
FROM A JOIN B ON koşul yazımında ON bölümü iki tablonun satırlarının nasıl eşleşeceğini söyler. Genellikle bu, yabancı anahtarın birincil anahtara eşitliğidir: e.student_id = s.id. ON koşulunu sağlayan her satır çifti sonuçta bir satır olur. INNER JOIN yalnızca iki tabloda da eşi olan satırları tutar.
SELECT s.first_name, e.course_id, e.score
FROM students AS s
INNER JOIN enrollments AS e ON e.student_id = s.id
WHERE s.city = 'Bakı'
ORDER BY s.id, e.course_id;▸ Beklenen çıktı
first_name | course_id | score Aysel | 1 | 92 Aysel | 6 | 88 Leyla | 2 | 95 Leyla | 7 | 90 Rəşad | 3 | 77 Rəşad | 6 | 99 Kamran | 6 | 91
Bir sorgu içinde tabloya verilen kısa ad: students AS s. Sonra sütunlar s.first_name biçiminde yazılır. İki tabloda aynı adlı bir sütun varsa (ikisinde de id var) önek zorunludur; yoksa VTYS hangi id sütununun kastedildiğini anlayamaz.
Birden fazla JOIN art arda yazılabilir. Aşağıda üç tabloyu birleştiriyoruz: her kayda öğrencinin adını ve dersin adını ekleyip yalnızca matematik derslerini bırakıyoruz.
SELECT s.first_name, c.title, e.score
FROM enrollments AS e
JOIN students AS s ON s.id = e.student_id
JOIN courses AS c ON c.id = e.course_id
WHERE c.subject = 'Math'
ORDER BY c.title, e.score DESC;▸ Beklenen çıktı
first_name | title | score Fidan | Algebra | 97 Aysel | Algebra | 92 Nigar | Algebra | 85 Murad | Algebra | 75 Leyla | Geometry | 95 Səbinə | Geometry | 79 Orxan | Geometry | 70
LEFT JOIN: eşi olmayan satırları korumak
Monitor hiç sipariş edilmemiş. INNER JOIN onu sonuçtan basitçe atardı. LEFT JOIN ise soldaki tablonun (FROM sözcüğünden sonra yazılanın) tüm satırlarını tutar; sağdaki tabloda eşi yoksa o sütunlar NULL ile doldurulur.
SELECT p.name, o.id AS order_id, o.quantity
FROM products AS p
LEFT JOIN orders AS o ON o.product_id = p.id
WHERE p.category = 'Electronics'
ORDER BY p.id, o.id;▸ Beklenen çıktı
name | order_id | quantity Laptop | 1 | 1 Smartphone | 4 | 1 Smartphone | 7 | 1 Headphones | 2 | 2 Headphones | 11 | 1 Monitor | NULL | NULL
Bu, çok yararlı bir yöntemi mümkün kılar: eşi olmayan satırları bulmak. LEFT JOIN sonrasında sağdaki tablonun birincil anahtarı NULL ise eş bulunamamıştır. “Kimsenin almadığı ürünler” ya da “hiçbir derse kayıtlı olmayan öğrenciler” gibi sorular böyle cevaplanır.
SELECT p.name
FROM products AS p
LEFT JOIN orders AS o ON o.product_id = p.id
WHERE o.id IS NULL;▸ Beklenen çıktı
name Monitor
JOIN ve GROUP BY birlikte
Birleştirilmiş sonuç da gruplanabilir. Geçen dersin sorusuna dönelim, ama bu kez müşteri adları ve harcadıkları parayla: her siparişi müşterisine ve ürününe bağlıyor, miktarı fiyatla çarpıp her müşteri için topluyoruz.
SELECT c.name,
COUNT(o.id) AS orders,
ROUND(SUM(o.quantity * p.price), 2) AS total_spent
FROM customers AS c
JOIN orders AS o ON o.customer_id = c.id
JOIN products AS p ON p.id = o.product_id
GROUP BY c.id, c.name
ORDER BY total_spent DESC;▸ Beklenen çıktı
name | orders | total_spent Anar Mustafayev | 3 | 1723 Emre Yılmaz | 2 | 941.99 Zəhra Hüseynli | 2 | 935.99 Lalə Əhmədova | 2 | 184.5 John Carter | 1 | 69.98 Olga Ivanova | 1 | 55 Mehmet Kaya | 1 | 31.6
LEFT JOIN sonrasında sayarken dikkatli ol: COUNT(*) Monitor için 1 verirdi, çünkü NULL değerlerle dolu bir satır da bir satırdır. COUNT(o.id) ise yalnızca gerçek siparişleri sayar ve 0 döndürür. COALESCE(SUM(...), 0) boş bir toplamı sıfıra çevirir.
SELECT p.name,
COUNT(o.id) AS times_ordered,
COALESCE(SUM(o.quantity), 0) AS units
FROM products AS p
LEFT JOIN orders AS o ON o.product_id = p.id
GROUP BY p.id, p.name
ORDER BY units DESC, p.name;▸ Beklenen çıktı
name | times_ordered | units Notebook | 2 | 30 Pen set | 1 | 4 Headphones | 2 | 3 Water bottle | 1 | 3 Desk lamp | 1 | 2 Smartphone | 2 | 2 Backpack | 1 | 1 Chess set | 1 | 1 Laptop | 1 | 1 Monitor | 0 | 0
Diğer birleştirme türleri
| Tür | Neyi tutar | Destek |
|---|---|---|
| INNER JOIN | yalnızca iki tabloda da eşi olan satırları | hepsinde |
| LEFT JOIN | soldaki tablonun tüm satırlarını | hepsinde |
| RIGHT JOIN | sağdaki tablonun tüm satırlarını | MySQL, PostgreSQL, SQL Server; SQLite 3.39 sürümünden beri |
| FULL OUTER JOIN | iki tablonun da tüm satırlarını | PostgreSQL, SQL Server, SQLite 3.39+; MySQL'de yok |
| CROSS JOIN | satırların tüm olası çiftlerini | hepsinde |
A RIGHT JOIN B, B LEFT JOIN A ile aynı sonucu verir; bu yüzden uygulamada çoğunlukla LEFT JOIN kullanılır.SELECT COUNT(*) AS pairs
FROM students, courses;▸ Beklenen çıktı
pairs 84
Miktarı en az 2 olan siparişleri göster: siparişin id değeri, müşterinin adı (customer), ürünün adı (product) ve miktar (quantity). Sonucu sipariş id değerine göre sırala.
SELECT o.id, o.customer_id, o.product_id, o.quantity
FROM orders AS o
WHERE o.quantity >= 2
ORDER BY o.id;▸ Beklenen çıktı
id | customer | product | quantity 2 | Anar Mustafayev | Headphones | 2 3 | Lalə Əhmədova | Notebook | 20 6 | John Carter | Desk lamp | 2 8 | Zəhra Hüseynli | Water bottle | 3 10 | Mehmet Kaya | Pen set | 4 12 | Anar Mustafayev | Notebook | 10
Electronics kategorisindeki her ürün için sipariş edilen toplam miktarı (units) göster; hiç sipariş edilmemiş ürün 0 ile görünmelidir. Sonucu units değerine göre azalan, sonra ada göre artan sırada sırala.
SELECT p.name, SUM(o.quantity) AS units
FROM products AS p
JOIN orders AS o ON o.product_id = p.id
WHERE p.category = 'Electronics'
GROUP BY p.id, p.name
ORDER BY units DESC, p.name;▸ Beklenen çıktı
name | units Headphones | 3 Smartphone | 2 Laptop | 1 Monitor | 0
Önemli noktalar
JOIN ... ON, iki tablonun satırlarını bir koşula göre, genellikle yabancı anahtar = birincil anahtar ile eşleştirir.INNER JOINyalnızca eşleşen satırları,LEFT JOINise soldaki tablonun tüm satırlarını tutar.LEFT JOIN ... WHERE sağ.id IS NULLeşi olmayan satırları bulur.- Tablo takma adları (
students AS s) sorguyu kısaltır ve aynı adlı sütunları ayırt eder. ONolmadan yapılan birleştirme tüm olası çiftleri üretir; bu genellikle bir hatadır.
Kendini test et
10 soru. Her doğru cevap XP kazandırır.
INNER JOIN hangi satırları döndürür?