Ana içeriğe geç
Kesit SQL
Orta · Kanat Havayolları

Uçuş, rota, havalimanı ve uçak: JOIN zinciri

Dört tabloyu adım adım birleştirmek, eşi olmayanı LEFT JOIN ile bulmak ve rötar nedenlerini özetlemek.

Uygulamada aç, 9 alıştırmayı çözÜcretsiz, hesap gerekmez, kurulum yok.

Bu sayfa dersin okuma sürümüdür. Metin bir kutuyu çalıştırmanı ya da adıma geçmeni söylüyorsa dersi uygulamada aç.

Bir uçuşun tam resmi

hv_flights tek başına “KN101 kalktı” der ama nereden nereye uçtuğunu, hangi uçakla uçtuğunu söylemez. Bunlar başka tablolardadır ve yabancı anahtarlarla bağlanır:

hv_flights.route_id ──> hv_routes.route_id ──> origin, dest ──> hv_airports.airport_code
hv_flights.tail_no  ──> hv_aircraft.tail_no
hv_bookings.flight_id ──> hv_flights.flight_id
hv_bookings.passenger_id ──> hv_passengers.passenger_id
SELECT f.flight_no, r.origin, r.dest, a.model, f.sched_dep
FROM hv_flights f
JOIN hv_routes r   ON r.route_id = f.route_id
JOIN hv_aircraft a ON a.tail_no = f.tail_no
WHERE f.sched_dep >= '2024-12-31' AND f.sched_dep < '2025-01-01'
ORDER BY f.sched_dep
LIMIT 5;

Doluluk oranı: iki tablodan gelen iki sayı

Doluluk (load factor) = binen yolcu ÷ koltuk. Yolcu uçuştan, koltuk uçaktan gelir:

SELECT a.model, ROUND(100.0 * SUM(f.pax) / SUM(a.seats), 1) AS doluluk
FROM hv_flights f
JOIN hv_aircraft a ON a.tail_no = f.tail_no
WHERE f.status <> 'cancelled'
GROUP BY a.model;
Oranların ortalaması değil, toplamların oranıHer uçuşun doluluğunu ayrı hesaplayıp ortalamasını almak, küçük ve büyük uçakları eşit ağırlıklandırır. Sektör tanımı toplam yolcu ÷ toplam koltuktur.

Derinleş: JOIN sonrası çoğalma: rötar tablosu örneği

JOIN'de en sinsi hata, sorgunun hata vermeden yanlış sayı üretmesidir. Bunun en yaygın sebebi, birleştirilen tablolardan birinin bir satıra birden çok eşleşme getirmesidir. Kanat'ta hv_delays tablosu buna iyi bir örnek: bir uçuşun birden çok rötar nedeni olabilir (ör. hava + geç gelen uçak). 1.228 rötarlı uçuşun 122'sinde iki neden kayıtlı.

SELECT 'JOIN sonrası' AS yontem, COUNT(*) AS satir, SUM(f.pax) AS yolcu
FROM hv_flights f
JOIN hv_delays d ON d.flight_id = f.flight_id
UNION ALL
SELECT 'önce tekilleştir', COUNT(*), SUM(f.pax)
FROM hv_flights f
JOIN (SELECT DISTINCT flight_id FROM hv_delays) d ON d.flight_id = f.flight_id;

İlk satırda 1.350 “uçuş” ve 215.146 yolcu var. İki nedenli her uçuş iki kez sayılmış. Doğru cevap 1.228 uçuş ve 195.874 yolcudur. “Rötardan etkilenen yolcu” sayısı yaklaşık 20 bin fazla raporlanırdı.

Çoğalmayı önlemenin üç yolu

YöntemNe zaman?
Önce özetle, sonra birleştir: JOIN (SELECT flight_id, SUM(minutes) ... GROUP BY flight_id)Çok taraftan bir sayı (toplam dakika) gerekiyorsa
EXISTS / IN: WHERE EXISTS (SELECT 1 FROM hv_delays ...)Yalnızca “rötarı var mı?” sorusu soruluyorsa
COUNT(DISTINCT ...)Sayım için işe yarar ama SUM(pax)'ı düzeltmez

Taneciği önceden bil

Her JOIN'den önce kendine şunu sor: “Sol tablodaki bir satır, sağ tabloda kaç satırla eşleşebilir?” hv_flights → hv_routes ve hv_flights → hv_aircraft çoka-bir ilişkilerdir; satır sayısı değişmez. hv_flights → hv_bookings ve hv_flights → hv_delays ise bire-çok ilişkilerdir; satır çoğalır. Bir sorguda iki ayrı bire-çok tabloyu aynı anda birleştirirsen (rezervasyonlar ve rötarlar) çoğalma çarpılarak büyür. Bu durumda her birini ayrı bir alt sorguda özetlemek gerekir.

Hızlı kontrolJOIN'den sonra COUNT(*) ile COUNT(DISTINCT f.flight_id)'yi karşılaştır. Eşit değillerse taneciğin değişti ve toplamların şişmiş olabilir.
Alıştırmalara geç (9)