#sql #entity-relationship
Вопрос:
Домен представляет собой систему бронирования авиабилетов. Пользователи могут забронировать рейс. Полет состоит из одной или нескольких ног.
┌─────┐ ┌──────┐ ┌───────┐
│ Leg ├────────┤Flight├──────┤Booking│
└─────┘ * * └──────┘1 * └───────┘
Чтобы показать пользователю список действительных рейсов, система должна выяснить, есть ли на рейсе свободные места. Максимальное количество доступных мест сохраняется в виде поля в Leg
таблице. Забронированные места хранятся в Booking
.
Полеты могут состоять из нескольких этапов. Например, может быть 3 ноги A -> B ->> C. И два рейса, которые должны быть забронированы пользователями:
- A -> B: Перелет из пункта А в пункт Б.
- A -> B ->> C: Перелет из A в C через B.
Я создал dbfiddle с попыткой группировки по ногам, которая дает мне количество забронированных мест на одну ногу. Но мне нужно сгенерировать список рейсов с наибольшим количеством забронированных пассажиров на один рейс. В приведенном выше примере: На рейсе 1 может быть меньше свободных мест, если пассажиры забронированы на рейс 2, потому что они оба «разделяют» первый этап.
select l.id as Leg, sum(b.number_passengers) as BookedSeats
FROM flight f
JOIN flight_legs fl on f.id = fl.flight_id
JOIN leg l on fl.legs_id = l.id
JOIN booking b on f.id = b.flight_id
GROUP BY l.id;
Как я могу создать список рейсов с доступными местами?
Пример
Схема
Нога
ID | места_доступны |
---|---|
1 | 2 |
2 | 2 |
Полет
ID |
---|
1 |
2 |
Flight_Leg
flight_id | leg_id | порядок ног |
---|---|---|
1 | 1 | 0 |
1 | 2 | 1 |
2 | 1 | 0 |
Примечание: У рейса 1 две ноги, а у рейса 2 только одна нога. Оба рейса «разделяют» один и тот же первый этап.
Бронирование
ID | flight_id | number_passengers |
---|---|---|
1 | 1 | 1 |
2 | 2 | 1 |
Примечание: Один человек забронировал рейс 1 и летит обеими ногами. Другой человек забронировал рейс 2 только с первым этапом. Это означает, что два пассажира на первом этапе и один пассажир на оставшемся этапе.
Ожидаемый результат
Найдите все рейсы с доступными местами. Места могут быть заняты и другими рейсами.
flight_id | свободные места |
---|---|
1 | 0 |
2 | 0 |
Примечание: На рейс 2 нет свободных мест, так как первый рейс полностью забронирован
Диаграмма
Комментарии:
1. Введите желаемые выходные данные и, если возможно, примерные данные
2. @LucasEthen Добавил объяснение примера dbfiddle.
Ответ №1:
Следующий запрос реализует желаемый результат. Я использовал эту Lag
функцию, чтобы перейти к предыдущей строке, если предыдущая часть была заполнена.
SELECT Leg,
case
when Free_Seats = 0 then 0
else (case when PrevLeg = 0 then 0 else Free_Seats end) end as Free_Seats
FROM (SELECT Leg,Free_Seats,LAG(Free_Seats,1) OVER(ORDER BY Leg) PrevLeg
FROM (SELECT l.id AS Leg,l.seats_available,b.number_passengers,fl.flight_id,
(max(l.seats_available) OVER(PARTITION BY fl.flight_id) - sum(b.number_passengers) OVER(PARTITION BY fl.flight_id)) AS Free_Seats,
ROW_NUMBER() OVER(PARTITION BY fl.flight_id ORDER BY fl.flight_id) AS seq
FROM flight f
JOIN flight_legs fl ON f.id = fl.flight_id
JOIN leg l ON fl.legs_id = l.id
JOIN booking b ON f.id = b.flight_id) T
WHERE t.seq=1) T
Комментарии:
1. Спасибо. Это дает мне свободные места на каждую ногу. Но мне нужны свободные места на рейс .
2. Я понимаю, но ваш желаемый результат неверен, потому что flight_id = 1 содержит две записи о ногах и в общей сложности четыре места, из которых осталось два места.
3. Тогда я не был ясен с моим примером: на первом этапе есть 1 пассажир из Бронирования 1 (забронированный рейс 1) и 1 пассажир из бронирования 2 (забронированный рейс 2). Поэтому рейс 1 должен предоставить 0 свободных мест, потому что на первом этапе забронировано два человека (но для разных рейсов). Рейс 2 также должен предоставить 0 свободных мест, потому что первый этап заполнен, хотя на втором этапе будет доступно свободное место. Обновлен ожидаемый результат.
4. Я реализовал ваш вывод. Я надеюсь, что это соответствует вашему запросу.
5. К сожалению, это не работает: независимо от того, сколько мест установлено для leg1, свободные места всегда равны 0 ( демо ). И это не дает мне свободных мест на рейс. Вместо этого он предоставляет бесплатные места для ног.