01 Занятие 01: Демонстрационная база данных / Авиаперевозки
Исходная страница в нативном Markdown: Демонстрационная база данных / Авиаперевозки
Примечание
Эта страница извлечена из официального PDF в нативный Markdown. Текст слайдов, код и комментарии сохранены в порядке чтения; исходные PDF и HTML остаются эталоном макета.
HTML source:qpt_01_demodb_bookings.htmlArchive:QPT-handouts-16.zipСтраниц PDF: 27
Page 1: Демонстрационная база данных / Авиаперевозки
Некоммерческое использование материалов курса (презентации, демонстрации) разрешается без ограничений. Коммерческое использование возможно только с письменного разрешения компании Postgres Professional. Запрещается внесение изменений в материалы курса.
Обратная связь
Отзывы, замечания и предложения направляйте по адресу: edu@postgrespro.ru
Отказ от ответственности
Компания Postgres Professional не несет никакой ответственности за любые повреждения и убытки, включая потерю дохода, нанесенные прямым или непрямым, специальным или случайным использованием материалов курса. Компания Postgres Professional не предоставляет каких-либо гарантий на материалы курса. Материалы курса предоставляются на основе принципа «как есть» и компания Postgres Professional не обязана предоставлять сопровождение, поддержку, обновления, расширения и изменения.
Демонстрационная база данных создавалась для таких задач, как:
● самостоятельное изучение языка запросов SQL;
● подготовка книг, пособий и учебных курсов по языку SQL;
● демонстрация возможностей PostgreSQL в статьях и заметках.
При разработке демонстрационной базы данных мы преследовали несколько целей:
● схема данных должна быть достаточно простой, чтобы быть понятной без особых пояснений;
● в то же время схема данных должна быть достаточно сложной, чтобы позволять строить осмысленные запросы;
● база данных должна быть наполнена данными, напоминающими реальные, с которыми будет интересно работать.
Демонстрационная база данных распространяется под лицензией PostgreSQL.
База данных доступна в трех вариантах, отличающихся размером. Например, в курсе по оптимизации запросов используется база большого объема, содержащая данные по полетам за один год.
В данной теме рассматривается версия демобазы от 15.08.2017.
{#source-figure-004 caption=“Source slide page 4: Общая схема”}
Комментарии преподавателя
Основной сущностью является бронирование (bookings).
В одно бронирование можно включить несколько пассажиров, каждому из которых выписывается отдельный билет (tickets).
Билет включает один или несколько перелетов (ticket_flights). Несколько перелетов могут включаться в билет в случаях, когда нет прямого рейса, соединяющего пункты отправления и назначения (полет с пересадками), либо когда билет взят «туда и обратно».
Каждый рейс (flights) следует из одного аэропорта (airports) в другой. Рейсы с одним номером имеют одинаковые пункты вылета и назначения, но будут отличаться датой отправления.
При регистрации на рейс пассажиру выдается посадочный талон (boarding_passes), в котором указано место в самолете. Пассажир может зарегистрироваться только на тот рейс, который есть у него в билете. Комбинация рейса и места в самолете уникальна.
Количество мест (seats) в самолете и их распределение по классам обслуживания зависит от модели самолета (aircrafts), выполняющего рейс. Предполагается, что каждая модель самолета имеет только одну компоновку салона.
На приведенной схеме отмечены только столбцы, соответствующие первичным и внешним ключам. Далее мы рассмотрим основные объекты демонстрационной базы данных подробнее.
Page 5: Бронирования
Bookings
пассажир заранее (за месяц) бронирует билет себе и, возможно,
нескольким другим пассажирам
book_ref
номер бронирования (комбинация букв и цифр)
book_date
дата бронирования
total_amount
общая стоимость включенных в бронирование билетов
Комментарии преподавателя
Пассажир заранее (book_date, максимум за месяц до рейса) бронирует билет себе и, возможно, нескольким другим пассажирам. Бронирование идентифицируется номером (book_ref, шестизначная комбинация букв и цифр).
Поле total_amount хранит общую стоимость включенных в бронирование перелетов всех пассажиров.
Столбец | Тип | Модификаторы | Описание
--------------+---------------+--------------+---------------------------
book_ref | char(6) | not null | Номер бронирования
book_date | timestamptz | not null | Дата бронирования
total_amount | numeric(10,2) | not null | Полная сумма бронирования
Индексы:
PRIMARY KEY, btree (book_ref)
Ссылки извне:
TABLE "tickets" FOREIGN KEY (book_ref) REFERENCES bookings(book_ref)
Page 6: Бронирование
Начнем с бронирования и выберем какое-нибудь одно:
?column?
------------------
20 days 18:24:00
(1 row)
Page 7: Билеты
Tickets
билет выдается на одного пассажира и может включать несколько
перелетов
ни идентификатор пассажира, ни имя не являются постоянными;
нельзя однозначно найти все билеты одного и того же пассажира
ticket_no
номер билета
book_ref
номер бронирования
passenger_id
идентификатор пассажира (номер документа)
passenger_name
имя пассажира
contact_data
контактные данные пассажира
Комментарии преподавателя
Билет имеет уникальный номер (ticket_no), состоящий из 13 цифр.
Билет содержит идентификатор пассажира (passenger_id) — номер документа, удостоверяющего личность, — его фамилию и имя (passenger_name) и контактную информацию (contact_data).
Ни идентификатор пассажира, ни имя не являются постоянными (можно поменять паспорт, можно сменить фамилию), поэтому однозначно найти все билеты одного и того же пассажира невозможно.
Столбец | Тип | Модификаторы | Описание
----------------+-------------+--------------+-----------------------------
ticket_no | char(13) | not null | Номер билета
book_ref | char(6) | not null | Номер бронирования
passenger_id | varchar(20) | not null | Идентификатор пассажира
passenger_name | text | not null | Имя пассажира
contact_data | jsonb | | Контактные данные пассажира
Индексы:
PRIMARY KEY, btree (ticket_no)
Ограничения внешнего ключа:
FOREIGN KEY (book_ref) REFERENCES bookings(book_ref)
Ссылки извне:
TABLE "ticket_flights" FOREIGN KEY (ticket_no) REFERENCES
tickets(ticket_no)
Page 8: Билеты
Посмотрим, какие билеты включены в выбранное бронирование:
Здесь мы смотрим только на один билет — все маршруты в одном бронировании всегда совпадают.
Видим, что в билете 6 перелетов; из них один бизнес-классом, другие — экономом.
Page 11: Рейсы
Flights
рейс выполняется по расписанию из одного аэропорта в другой
естественный ключ — номер рейса и дата отправления,
но используется суррогатный ключ
flight_id
идентификатор рейса
flight_no
номер рейса
scheduled_departure/arrival
вылет и прилет по расписанию
actual_departure/arrival
фактический вылет и прилет
departure/arrival_airport
аэропорты отправления и прибытия
status
статус рейса
aircraft_code
код самолета
Комментарии преподавателя
Рейс соединяет аэропорты вылета и прибытия. Если нет прямого рейса, в билет включаются несколько рейсов.
Столбец | Тип | Модификаторы | Описание
---------------------+-------------+--------------+----------------------------
flight_id | integer | not null | Идентификатор рейса
flight_no | char(6) | not null | Номер рейса
scheduled_departure | timestamptz | not null | Время вылета по расписанию
scheduled_arrival | timestamptz | not null | Время прилёта по расписанию
departure_airport | char(3) | not null | Аэропорт отправления
arrival_airport | char(3) | not null | Аэропорт прибытия
status | varchar(20) | not null | Статус рейса
aircraft_code | char(3) | not null | Код самолета, IATA
actual_departure | timestamptz | | Фактическое время вылета
actual_arrival | timestamptz | | Фактическое время прилёта
Индексы:
PRIMARY KEY, btree (flight_id)
UNIQUE CONSTRAINT, btree (flight_no, scheduled_departure)
Ограничения-проверки:
CHECK (scheduled_arrival > scheduled_departure)
CHECK ((actual_arrival IS NULL)
OR ((actual_departure IS NOT NULL AND actual_arrival IS NOT NULL)
AND (actual_arrival > actual_departure)))
CHECK (status IN ('On Time', 'Delayed', 'Departed',
'Arrived', 'Scheduled', 'Cancelled'))
Ограничения внешнего ключа:
FOREIGN KEY (aircraft_code) REFERENCES aircrafts_data(aircraft_code)
FOREIGN KEY (arrival_airport) REFERENCES airports_data(airport_code)
FOREIGN KEY (departure_airport) REFERENCES airports_data(airport_code)
Page 12: Рейсы
Теперь разберемся, какие рейсы скрываются за выбранными перелетами.
Видим три рейса «туда» и три «обратно». «Туда» все рейсы уже совершены (Arrived), а в настоящее время пассажир летит «обратно» (Departed). Следующий рейс будет по расписанию (On Time), а на последний еще не открыта регистрация (Scheduled).
Посмотрим внимательнее на все столбцы одного из рейсов.
Реальное время может отличаться от времени по расписанию (обычно не сильно).
Номер flight_no одинаков для всех рейсов, следующих по одному маршруту по расписанию:
реализация: многоязычное представление над airports_data
airport_code
код аэропорта
airport_name
название аэропорта
city
город
coordinates
координаты аэропорта (долгота и широта)
timezone
часовой пояс
Комментарии преподавателя
Аэропорт идентифицируется трехбуквенным кодом (airport_code) и имеет свое имя (airport_name).
Для города не предусмотрено отдельной сущности, но введено поле с названием города (city), позволяющее найти аэропорты одного города. Это представление также включает координаты аэропорта (coordinates) и часовой пояс (timezone).
Значения полей airport_name и city определяются в зависимости от выбранного в конфигурационном параметре bookings.lang языка.
Здесь видим и местное время в часовых поясах городов отправления и прибытия, длительность полета, названия аэропортов.
Page 15: Page 15
Поскольку в демобазе маршруты не меняются со временем, из таблицы рейсов можно выделить информацию, которая не зависит от конкретной даты вылета. Такая информация собрана в представлении routes:
=>SELECT*FROMroutesrWHEREr.flight_no='PG0412'\gx
-[ RECORD 1 ]----------+----------------
flight_no | PG0412
departure_airport | VKO
departure_airport_name | Внуково
departure_city | Москва
arrival_airport | PEE
arrival_airport_name | Пермь
arrival_city | Пермь
aircraft_code | 773
duration | 01:25:00
days_of_week | {1,2,3,4,5,6,7}
Видно, что рейсы выполняются ежедневно (массив days_of_week).
Page 16: Самолеты
Aircrafts
модели самолетов, выполняющие рейсы
реализация: многоязычное представление над aircrafts_data
aircraft_code
код самолета
model
модель самолета
range
максимальная дальность полета, км
Комментарии преподавателя
Каждая модель воздушного судна идентифицируется своим трехзначным кодом (aircraft_code). Указывается также название модели (model) и максимальная дальность полета в километрах (range).
Значение поля model определяется в зависимости от выбранного в конфигурационном параметре bookings.lang языка.
aircraft_code | model | range
---------------+---------------+-------
773 | Боинг 777-300 | 11100
(1 row)
Page 18: Места
Seats
места определяют схему салона
все самолеты одной модели имеют одну и ту же компоновку салона
aircraft_code
код самолета
seat_no
номер места
fare_conditions
класс обслуживания
Комментарии преподавателя
Места определяют схему салона каждой модели. Каждое место определяется своим номером (seat_no) и имеет закрепленный за ним класс обслуживания (fare_conditions) — Economy, Comfort или Business.
При регистрации на рейс, которая возможна за сутки до плановой даты отправления, пассажиру выдается посадочный талон. Он идентифицируется так же, как и перелет — номером билета и номером рейса.
Посадочным талонам присваиваются последовательные номера (boarding_no) в порядке регистрации пассажиров на рейс (этот номер будет уникальным только в пределах данного рейса). В посадочном талоне указывается номер места (seat_no).
Столбец | Тип | Модификаторы | Описание
-------------+------------+--------------+--------------------------
ticket_no | char(13) | not null | Номер билета
flight_id | integer | not null | Идентификатор рейса
boarding_no | integer | not null | Номер посадочного талона
seat_no | varchar(4) | not null | Номер места
Индексы:
PRIMARY KEY, btree (ticket_no, flight_id)
UNIQUE CONSTRAINT, btree (flight_id, boarding_no)
UNIQUE CONSTRAINT, btree (flight_id, seat_no)
Ограничения внешнего ключа:
FOREIGN KEY (ticket_no, flight_id)
REFERENCES ticket_flights(ticket_no, flight_id)
Page 21: Посадочные талоны
На каких местах сидел наш пассажир? Для этого надо заглянуть в посадочный талон, который выдается при регистрации на рейс:
На два оставшихся рейса пассажир еще не зарегистрировался.
Page 22: Многоязычность
Конфигурационный параметр
bookings.lang
Таблицы для хранения многоязычных названий
airports_data
aircrafts_data
Комментарии преподавателя
Язык, на котором выводятся названия городов, аэропортов и моделей самолетов, переключается с помощью конфигурационного параметра bookings.lang. В состав демобазы входят названия на русском (ru) и английском (en) языках.
Можно самостоятельно расширить языковую поддержку, добавив в строки таблиц airports_data и aircrafts_data названия на произвольном языке.
Page 23: Многоязычность
В демобазе заложена возможность перевода названий аэропортов, городов и самолетов на другие языки. Как мы видели, по умолчанию все названия выводятся по-русски:
-[ RECORD 1 ]+---------------------------------------------------------
airport_code | VKO
airport_name | {"en": "Vnukovo International Airport", "ru": "Внуково"}
city | {"en": "Moscow", "ru": "Москва"}
coordinates | (37.2615013123,55.5914993286)
timezone | Europe/Moscow
Page 24: Итоги
Схема демобазы достаточно проста, но позволяет писать сложные и интересные запросы
Данные в демобазе похожи на настоящие
Демобазу можно использовать для изучения языка SQL, демонстрации возможностей PostgreSQL и т. п.
Page 25: Практика
Напишите несколько запросов к демонстрационной базе данных. 1. Сколько человек бывает включено в одно бронирование? 2. До каких городов нельзя добраться из Москвы без пересадок? 3. Какая модель самолета выполняет больше всего рейсов, а какая — меньше всего? 4. А какая модель перевезла больше всего пассажиров?
В результате будет два столбца:
Количество человек в бронировании
Число бронирований
Page 26: 1. Сколько человек в одном бронировании?
Посчитаем количество человек в каждом бронировании, а затем число бронирований для каждого количества.