İçeriğe geç
Educora
Orta18 dk8 / 22

JOIN: tabloları birleştirme

INNER JOIN ve LEFT JOIN ile birkaç tablonun verisini tek bir sonuçta birleştir, eşi olmayan satırları bul ve birleştirmeden sonra grupla.

Kendini test et
Bu derste öğreneceklerin
  • INNER JOIN ile ilişkili tabloları bir ON koşuluna göre birleştirmek
  • LEFT JOIN ile eşi olmayan satırları korumak ve bulmak
  • Tablo takma adlarını ve birleştirmeden sonra GROUP BY kullanmak

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.

SQL
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
Bakülü öğrencilerin kayıtları. Aysel iki derse kayıtlı olduğu için iki kez görünür.
Tanım
Tablo takma adı

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.

SQL
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.

SQL
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.

SQL
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
Hiç sipariş edilmemiş ürünler.

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.

SQL
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.

SQL
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ürNeyi tutarDestek
INNER JOINyalnızca iki tabloda da eşi olan satırlarıhepsinde
LEFT JOINsoldaki tablonun tüm satırlarınıhepsinde
RIGHT JOINsağdaki tablonun tüm satırlarınıMySQL, PostgreSQL, SQL Server; SQLite 3.39 sürümünden beri
FULL OUTER JOINiki tablonun da tüm satırlarınıPostgreSQL, SQL Server, SQLite 3.39+; MySQL'de yok
CROSS JOINsatırların tüm olası çiftlerinihepsinde
A RIGHT JOIN B, B LEFT JOIN A ile aynı sonucu verir; bu yüzden uygulamada çoğunlukla LEFT JOIN kullanılır.
SQL
SELECT COUNT(*) AS pairs
FROM students, courses;
▸ Beklenen çıktı
pairs
84
Alıştırma

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.

Alıştırma · SQL
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
Alıştırma

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.

Alıştırma · SQL
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 JOIN yalnızca eşleşen satırları, LEFT JOIN ise soldaki tablonun tüm satırlarını tutar.
  • LEFT JOIN ... WHERE sağ.id IS NULL eşi olmayan satırları bulur.
  • Tablo takma adları (students AS s) sorguyu kısaltır ve aynı adlı sütunları ayırt eder.
  • ON olmadan 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.

1 / 10
INNER JOIN hangi satırları döndürür?