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;
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öntem | Ne 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.
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.