Эта задача — отличный пример использования одного из самых мощных инструментов SQL для анализа связей в данных: соединения таблицы саму с собой (SELF JOIN). Давайте разберем логику решения по шагам.
Нам нужно найти все возможные варианты перелёта из аэропорта Пулково (LED) в Брянск (BZK), которые включают ровно одну пересадку.
Маршрут с одной пересадкой — это не один, а два независимых рейса, связанных между собой промежуточным аэропортом.
Наша цель — найти все такие пары рейсов, где аэропорт прибытия первого рейса совпадает с аэропортом вылета второго.
Чтобы реализовать эту логику, мы обращаемся к таблице рейсов так, как будто это две разные таблицы. Мысленно создадим для неё два псевдонима, например, first_leg (первый сегмент) и second_leg (второй сегмент).
Определяем первый сегмент пути. Мы используем псевдоним first_leg для поиска всех рейсов, которые вылетают из нашего начального пункта.
first_leg.departure_airport = 'LED'.Определяем второй сегмент пути. Используя псевдоним second_leg, мы ищем все рейсы, которые прилетают в наш конечный пункт.
second_leg.arrival_airport = 'BZK'.Находим точку стыковки (ключевое условие JOIN). Теперь самое главное: нам нужно соединить эти два набора рейсов. Мы объединяем их по условию, что аэропорт прилёта первого сегмента должен в точности совпадать с аэропортом вылета второго.
first_leg.arrival_airport = second_leg.departure_airport.connection_airport).Проверяем время пересадки: Нам также нужно убедиться, что второй рейс вылетает после того, как прилетит первый. Это обеспечивается условием:
second_leg.scheduled_departure > first_leg.scheduled_arrival - Это условие гарантирует, что мы рассматриваем только те пересадки, где достаточно времени для осуществления пересадки между рейсами.Формируем результат. После того как таблицы соединены, у нас есть вся необходимая информация в одной строке. Мы можем выбрать:
first_leg (departure_airport).first_leg.arrival_airport или, что то же самое, second_leg.departure_airport).second_leg (arrival_airport).Таким образом, SELF JOIN позволяет нам "развернуть" одну таблицу и сопоставить строки из неё друг с другом, находя сложные, многоступенчатые маршруты.
select
first_leg.flight_no flight1_no,
first_leg.departure_airport,
first_leg.arrival_airport connection_airport,
first_leg.scheduled_arrival - first_leg.scheduled_departure flight1_time,
second_leg.scheduled_departure - first_leg.scheduled_arrival connection_time,
second_leg.flight_no flight2_no,
second_leg.arrival_airport,
second_leg.scheduled_arrival - second_leg.scheduled_departure flight2_time,
(second_leg.scheduled_arrival - first_leg.scheduled_departure) total_trip_time
from flights first_leg
join flights second_leg on first_leg.arrival_airport=second_leg.departure_airport
and second_leg.arrival_airport = 'BZK'
and second_leg.scheduled_departure > first_leg.scheduled_arrival
where first_leg.departure_airport = 'LED'
and first_leg.scheduled_departure between '2017-08-16' and '2017-08-17'
and second_leg.scheduled_departure between '2017-08-16' and '2017-08-17'
order by (second_leg.scheduled_arrival - first_leg.scheduled_departure)
limit 1;