Задача состоит в том, чтобы рассчитать средний процент заполняемости самолетов для каждого класса обслуживания (Бизнес и Эконом) в разрезе аэропортов вылета. Иными словами, нужно выяснить, насколько в среднем были заполнены бизнес- и эконом-классы на рейсах, вылетающих из каждого аэропорта.
Шаг 1: Сбор данных по каждому рейсу.
total_seats).occupied_seats).flights — основная информация о рейсах, включая flight_id и aircraft_code.seats — информация о всех местах в каждом самолете (aircraft_code) и их классе обслуживания (fare_conditions).boarding_passes — информация о выданных посадочных талонах, которая говорит нам, какие места на каком рейсе были заняты.LEFT JOIN для таблицы boarding_passes. Это позволяет нам учесть все места в самолете, даже те, на которые не были выданы посадочные талоны (т.е. свободные места).Шаг 2: Расчет заполняемости для каждого рейса.
flight_id, мы можем посчитать количество занятых и общее количество мест для каждого класса.COUNT(...) FILTER (WHERE ...)), мы подсчитываем места отдельно для 'Business' и 'Economy'.(занятые_места / всего_мест) * 100.Шаг 3: Агрегация по аэропортам вылета.
departure_airport).AVG(), мы находим среднее значение процента заполняемости по всем рейсам, вылетевшим из данного аэропорта. Это и будет финальным результатом.Таким образом, решение строится на двух уровнях агрегации: сначала по каждому рейсу, а затем по каждому аэропорту.
with occupancy as (
select
flights.flight_id, departure_airport,
count(boarding_passes.seat_no) filter (where seats.fare_conditions = 'Business') business_occupancy,
(count(seats.seat_no) filter (where seats.fare_conditions = 'Business'))::numeric business_seats,
count(boarding_passes.seat_no) filter (where seats.fare_conditions = 'Economy') economy_occupancy,
(count(seats.seat_no) filter (where seats.fare_conditions = 'Economy'))::numeric economy_seats
from flights
join seats using (aircraft_code)
left join boarding_passes on
boarding_passes.seat_no = seats.seat_no and
boarding_passes.flight_id = flights.flight_id
where flights.actual_departure between '2017-08-01' and '2017-09-01'
group by flights.flight_id, departure_airport
) select
departure_airport,
(avg(case when business_seats > 0 then business_occupancy / business_seats end) * 100)::numeric(5, 2) average_business_occupancy,
(avg(case when economy_seats > 0 then economy_occupancy / economy_seats end) * 100)::numeric(5, 2) average_economy_occupancy
from occupancy
group by departure_airport
order by departure_airport;