Демонстрационная база данных

Представляем вам демонстрационную базу данных для СУБД PostgreSQL. В качестве предметной области мы используем авиаперевозки.
База данных может использоваться, например,
- для самостоятельного изучения языка запросов SQL,
- для подготовки книг, пособий и учебных курсов по языку SQL,
- для демонстрации возможностей PostgreSQL в статьях и заметках.
При разработке демонстрационной базы данных мы преследовали несколько целей:
- схема данных должна быть достаточно простой, чтобы быть понятной без особых пояснений,
- в то же время схема данных должна быть достаточно сложной, чтобы позволять строить осмысленные запросы,
- база данных должна быть наполнена данными, напоминающими реальные, с которыми будет интересно работать.
Демонстрационная база данных распространяется под лицензией MIT.
Свои замечания и пожелания направляйте нам по адресу [email protected].
Версия от 01.09.2025
Установка
Демонстрационная база данных доступна в четырёх версиях, которые отличаются объёмом данных:
- demo-20250901-3m.sql.gz (133 Мбайт) — данные по полётам за три месяца (размер БД примерно 1,3 Гбайт),
- demo-20250901-6m.sql.gz (276 МБ) — данные по полётам за шесть месяцев (размер БД примерно 2,7 Гбайт),
- demo-20250901-1y.sql.gz (558 Мбайт) — данные по полётам за год (размер БД примерно 5,4 Гбайт).
- demo-20250901-2y.sql.gz (1137 Мбайт) — данные по полётам за два года (размер БД примерно 11 Гбайт).
Небольшая база годится для того, чтобы писать запросы, и при этом не займёт много места на диске. База большого размера позволит почувствовать, как ведут себя запросы на больших объёмах данных, и задуматься об оптимизации.
Файлы содержат SQL-скрипт, создающий базу данных demo
и наполняющий её данными (фактически, это резервная копия, созданная утилитой pg_dump
). Владельцем базы данных demo
станет пользователь СУБД, выполнявший скрипт. Например, чтобы создать небольшую базу данных, запустите скрипт от имени пользователя postgres
в программе psql
:
gunzip -c demo-20250901-3m.sql.gz | psql -U postgres
Обратите внимание, что если база данных demo
уже существует, она будет удалена и создана заново!
Минимальная поддерживаемая версия — PostgreSQL 15.
Создать собственный вариант демобазы можно с помощью генератора.
Отличия от предыдущей версии
- Маршрутная сеть расширена на 17 стран: Россия, Китай, Индия, США, Канада, Япония, Франция, Германия, Италия, Великобритания, Чили, Швеция, Непал, Финляндия, Новая Зеландия, Австрия и Чехия. В этот список вошли страны ведущих разработчиков PostgreSQL, а также несколько других стран, имеющих определенное отношение к PostgreSQL.
- Количество аэропортов в таблице
airports_data
увеличено до примерно 5500. В маршрутной сети участвует менее сотни аэропортов, но большое количество строк в таблице позволяет демонстрировать индексирование точек методами GiST и SP-GiST. - В таблицу
airports_data
добавлена страна: столбецcountry
типаjsonb
с переводами, аналогичноairport_name
иcity
. Отдельного справочника стран в демобазе нет. - Таблица
aircrafts
переименована вairplanes
. Прежнее название было неудачным, поскольку в английском языке слово aircraft не меняется во множественном числе. - Изменился авиапарк: используются более новые и более крупные самолёты. Из десяти моделей две являются грузовыми и не участвуют в пассажирских авиаперевозках.
- Из таблицы
tickets
убран столбецcontact_info
, поскольку его простая структура не позволяла демонстрировать средства работы с JSON. Разнообразный JSON можно получить, например, агрегацией бронирований со вложенными билетами и перелетами. - Номер документа
tickets.passenger_id
однозначно определяет пассажира (одному номеру документа всегда соответствует одно и то же имяpassenger_name
, хотя в разных документах имена, конечно, могут совпадать). В дополнение к цифрам номер документа содержит код страны. - Регистрация выполняется только на первый рейс в билете. При этом выдаются посадочные талоны сразу на все входящие в билет рейсы.
- На обратный рейс пассажиру выдается отдельный билет. Прямые рейсы отмечены в столбце
tickets.outbound
типаboolean
значениемtrue
, а обратные —false
. В таблицуtickets
добавлено ограничение уникальности на столбцыbook_ref
,passenger_id
иoutbound
(на одного пассажира можно забронировать только два билета — прямой и обратный). - Таблица
ticket_flights
переименована вsegments
, а столбецamount
— в более точноеprice
. - Число пересадок ограничено четырьмя.
- Представление
routes
стало полноценной таблицей, определяющей маршруты. Маршруты меняются со временем, поэтому первичный ключ является темпоральным. Его составляют номер маршрутаroute_no
(ранее называвшийся номером рейсаflight_no
) и интервал действияvalidity
. Ключ реализован ограничением-исключением (полноценная поддержка темпоральных ключей появится в PostgreSQL 18). - Из таблицы
flights
в таблицуroutes
перенесены столбцыdeparture_airport
,arrival_airport
,airplane_code
. Таблицы соединяются по условиюroutes.route_no = flights.route_no AND routes.validity @> flights.scheduled_departure
. - Статус рейса
flights.status
принимает новое значениеBoarding
во время посадки пассажиров. - В таблицу
boarding_passes
добавлен столбецboarding_time
— время посадки в самолёт. Вместе со столбцомboarding_no
может иметь неопределенное значение в промежутке между регистрацией и посадкой на рейс. - Новое представление
timetable
скрывает темпоральное соединениеroutes
иflights
, а также выводит время в часовом поясе аэропортов. Чтобы облегчить переход к новой версии демобазы, можно использовать это представление вместо старой таблицыflights
или удалённого представленияflights_v
. - Ряд столбцов использует тип
text
вместо различных модификацийchar
иvarchar
: номер документаpassenger_id
, статус рейсаstatus
, номер маршрутаroute_no
, номер местаseat_no
и класс обслуживанияfare_conditions
. - Пассажиры, опоздавшие на стыковочный рейс (прибывшие в аэропорт менее чем за 40 минут до вылета), не попадают ни на этот рейс, ни на следующие рейсы в том же билете.
Схема данных
Основной сущностью является бронирование (bookings
).
В одно бронирование можно включить несколько пассажиров, каждому из которых выписывается билет (tickets
) на поездку в прямом направлении, а также отдельный обратный билет, если билеты приобретаются «туда и обратно». Билет имеет уникальный номер и содержит информацию о пассажире. Для пассажира нет отдельной сущности, но можно считать, что номер документа уникально идентифицирует пассажира.
Билет включает один перелет (segment
), если между пунктами отправления и назначения есть прямой рейс, и несколько перелетов, если требуются пересадки. Все билеты в одном бронировании имеют одинаковый набор перелетов, хотя в схеме данных такого ограничения нет.
Маршруты (routes
) проложены из одного аэропорта (airports
) в другой. Каждый рейс (flights
) следует по определенному маршруту, так что рейсы с одним номером маршрута имеют одинаковые пункты вылета и назначения, но отличаются датой отправления.
Маршрутная сеть меняется раз в месяц, поэтому рейсы и маршруты связаны темпоральным внешним ключом: при соединении следует учитывать не только номер маршрута, но и соответствие времени отправления интервалу действия маршрута. Для упрощения запросов можно использовать представление timetable
, скрывающее соединение этих таблиц.
Все перелеты считаются стыковочными: пассажир проходит регистрацию на первый рейс и сразу получает посадочные талоны (boarding_passes
) на все рейсы в своем билете. В посадочном талоне указано место, а также фиксируется время посадки в самолёт. Пассажир может зарегистрироваться только на тот рейс, который есть у него в билете. Комбинация рейса и места в самолёте уникальна, чтобы не допустить выдачу двух посадочных талонов на одно место.
Количество мест (seats
) в самолёте и их распределение по классам обслуживания зависит от модели самолёта (airplanes
), выполняющего рейс. Предполагается, что каждая модель самолёта имеет только одну компоновку салона. Схема данных не контролирует, что места в посадочных талонах соответствуют имеющимся в самолёте (такая проверка может быть сделана с использованием табличных триггеров или в приложении).
Объекты схемы
Схема bookings
содержит все объекты демонстрационной базы:
Имя | Тип | Описание
-----------------------+--------------------+----------------------
airplanes | представление | Самолёты
airplanes_data | таблица | Самолёты (переводы)
airports | представление | Аэропорты
airports_data | таблица | Аэропорты (переводы)
boarding_passes | таблица | Посадочные талоны
bookings | таблица | Бронирования
flights | таблица | Рейсы
flights_flight_id_seq | последовательность |
routes | таблица | Маршруты
seats | таблица | Места
segments | таблица | Перелёты
tickets | таблица | Билеты
timetable | представление | Расписание
При подключении к базе параметр конфигурации search_path
автоматически принимает значение bookings,"$user",public
, так что явно указывать имя схемы необязательно.
Однако для функций bookings.now
и bookings.version
в любом случае необходимо явно указывать схему, чтобы отличать их от одноимённых стандартных функций.
Представление bookings.airplanes
Каждая модель воздушного судна идентифицируется трёхзначным кодом ИАТА (airplane_code
). Указывается также название модели (model
), максимальная дальность полета в километрах (range
) и крейсерская скорость в километрах в час (speed
).
Значение поля model
определяется в зависимости от выбранного языка (параметр bookings.lang
).
Столбец | Тип | Описание
---------------+---------+------------------------------------
airplane_code | char(3) | Код самолёта, ИАТА
model | text | Модель самолёта
range | integer | Максимальная дальность полета, км
speed | integer | Крейсерская скорость, км/ч
Определение представления:
SELECT airplane_code,
model ->> lang() AS model,
range,
speed
FROM airplanes_data ml;
Таблица bookings.airplanes_data
Это базовая таблица для представления airplanes
. Поле model
этой таблицы содержит переводы моделей самолётов на разные языки, в формате JSONB. В большинстве случаев к этой таблице не следует обращаться напрямую.
Столбец | Тип | Допустимость NULL | Описание
---------------+---------+-------------------+-----------------------------------
airplane_code | char(3) | not null | Код самолёта, ИАТА
model | jsonb | not null | Модель самолёта
range | integer | not null | Максимальная дальность полета, км
speed | integer | not null | Крейсерская скорость, км/ч
Индексы:
PRIMARY KEY, btree (airplane_code)
Ограничения-проверки:
CHECK (range > 0)
CHECK (speed > 0)
Ссылки извне:
TABLE "routes" FOREIGN KEY (airplane_code)
REFERENCES airplanes_data(airplane_code)
TABLE "seats" FOREIGN KEY (airplane_code)
REFERENCES airplanes_data(airplane_code) ON DELETE CASCADE
Представление bookings.airports
Аэропорт идентифицируется трёхбуквенным кодом ИАТА (airport_code
) и имеет своё имя (airport_name
).
Для города и страны не предусмотрено отдельных сущностей, но введены поля city
и country
, позволяющее найти аэропорты одного города или страны. Это представление также включает координаты аэропорта (coordinates
) и часовой пояс (timezone
).
Значения полей airport_name
, city
и country
определяются в зависимости от выбранного языка (параметр bookings.lang
).
Столбец | Тип | Описание
--------------+---------+------------------------------------------
airport_code | char(3) | Код аэропорта, ИАТА
airport_name | text | Название аэропорта
city | text | Город
country | text | Страна
coordinates | point | Координаты аэропорта (долгота и широта)
timezone | text | Часовой пояс аэропорта
Определение представления:
SELECT airport_code,
airport_name ->> lang() AS airport_name,
city ->> lang() AS city,
country ->> lang() AS country,
coordinates,
timezone
FROM airports_data ml;
Таблица bookings.airports_data
Это базовая таблица для представления airports
. Она содержит переводы значений airport_name
, city
и country
на разные языки, в формате JSONB. В большинстве случаев к этой таблице не следует обращаться напрямую.
Столбец | Тип | Допустимость NULL | Описание
--------------+---------+-------------------+-----------------------------------------
airport_code | char(3) | not null | Код аэропорта, ИАТА
airport_name | jsonb | not null | Название аэропорта
city | jsonb | not null | Город
country | jsonb | not null | Страна
coordinates | point | not null | Координаты аэропорта (долгота и широта)
timezone | text | not null | Часовой пояс аэропорта
Индексы:
PRIMARY KEY, btree (airport_code)
Ссылки извне:
TABLE "routes" FOREIGN KEY (arrival_airport)
REFERENCES airports_data(airport_code)
TABLE "routes" FOREIGN KEY (departure_airport)
REFERENCES airports_data(airport_code)
Таблица bookings.boarding_passes
При регистрации на первый рейс, которая возможна за сутки до плановой даты отправления, пассажиру выдаются посадочные талоны на все рейсы в билете. В посадочном талоне указывается номер места (seat_no
). Посадочный талон идентифицируется также, как и перелёт — номером билета и идентификатором рейса.
При посадке пассажиров в самолёт посадочным талонам присваиваются последовательные номера (boarding_no
, этот номер уникален только в пределах данного рейса) и фиксируется время посадки (boarding_time
).
Столбец | Тип | Допустимость NULL | Описание
---------------+-------------+-------------------+--------------------------
ticket_no | text | not null | Номер билета
flight_id | integer | not null | Идентификатор рейса
seat_no | text | not null | Номер места
boarding_no | integer | | Номер посадочного талона
boarding_time | timestamptz | | Время посадки
Индексы:
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 segments(ticket_no, flight_id)
Таблица bookings.bookings
Продажа билетов начинается за 60 дней до рейса. Пассажир заранее (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)
Таблица bookings.flights
Естественный ключ таблицы рейсов состоит из двух полей — номера маршрута (route_no
) и плановой даты отправления (scheduled_departure
). Чтобы сделать внешние ключи на эту таблицу компактнее, в качестве первичного используется суррогатный ключ (flight_id
).
У каждого рейса есть запланированные дата и время вылета (scheduled_departure
) и прибытия (scheduled_arrival
). Реальные время вылета (actual_departure
) и прибытия (actual_arrival
) могут отличаться: обычно не сильно, но иногда и на несколько часов, если рейс задержан.
Статус рейса (status
) может принимать одно из следующих значений:
Scheduled
. Рейс доступен для бронирования. Это происходит за 60 дней до плановой даты вылета; до этого запись о рейсе не существует в базе данных.On Time
. Открыта регистрация (за сутки до плановой даты вылета) и рейс не задержан.Delayed
. Открыта регистрация (за сутки до плановой даты вылета), но рейс задержан.Boarding
. Идет посадка пассажиров в самолёт.Departed
. Самолёт вылетел и находится в воздухе.Arrived
. Самолёт прибыл в пункт назначения.Cancelled
. Рейс отменён.
Столбец | Тип | Допустимость NULL | Описание
---------------------+-------------+-------------------+-----------------------------
flight_id | integer | not null | Идентификатор рейса
route_no | text | not null | Номер маршрута
status | text | not null | Статус рейса
scheduled_departure | timestamptz | not null | Время вылета по расписанию
scheduled_arrival | timestamptz | not null | Время прилёта по расписанию
actual_departure | timestamptz | | Фактическое время вылета
actual_arrival | timestamptz | | Фактическое время прилёта
Индексы:
PRIMARY KEY, btree (flight_id)
UNIQUE CONSTRAINT, btree (route_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 ( 'Scheduled', 'On Time', 'Delayed', 'Boarding',
'Departed', 'Arrived', 'Cancelled'))
Ссылки извне:
TABLE "segments" FOREIGN KEY (flight_id)
REFERENCES flights(flight_id)
Таблица routes
Маршрут всегда соединяет две точки &mddash; аэропорты вылета (departure_airport
) и прибытия (arrival_airport
). Такое понятие, как «маршрут с пересадками» отсутствует: если из одного аэропорта до другого нет прямого рейса, в билет просто включаются несколько перелетов.
Маршрут имеет период действия (validity
) длиной в месяц. Маршрут между теми же аэропортами может повторяться неоднократно; он будет иметь тот же номер route_no
, однако в разные периоды может обслуживаться разными самолётами и отправляться в разные дни.
Рейсы, следующие данным маршрутом, обслуживается определенным типом самолёта (airplane_code
) и вылетают в одно и то же время (scheduled_time
, местное время в аэропорту отправления) в разные дни недели (массив days_of_week
, 1 — понедельник, 7 — воскресенье).
Столбец | Тип | Допустимость NULL | Описание
---------------------+-------------+-------------------+-----------------------------
route_no | text | not null | Номер маршрута
validity | tstzrange | not null | Период действия
departure_airport | char(3) | not null | Аэропорт отправления
arrival_airport | char(3) | not null | Аэропорт прибытия
airplane_code | char(3) | not null | Код самолёта, ИАТА
days_of_week | integer[] | not null | Дни недели, когда выполняются рейсы
scheduled_time | time | not null | Местное время вылета по расписанию
duration | interval | not null | Планируемая длительность полёта
Индексы:
btree (departure_airport, lower(validity))
EXCLUDE USING gist (route_no WITH =, validity WITH &&)
Ограничения внешнего ключа:
FOREIGN KEY (airplane_code) REFERENCES airplanes_data(airplane_code)
FOREIGN KEY (arrival_airport) REFERENCES airports_data(airport_code)
FOREIGN KEY (departure_airport) REFERENCES airports_data(airport_code)
Таблица bookings.seats
Места определяют схему салона каждой модели. Каждое место определяется своим номером (seat_no
) и имеет закреплённый за ним класс обслуживания (fare_conditions
) — Economy, Comfort или Business.
Столбец | Тип | Допустимость NULL | Описание
-----------------+-------------+-------------------+--------------------
airplane_code | char(3) | not null | Код самолёта, ИАТА
seat_no | text | not null | Номер места
fare_conditions | text | not null | Класс обслуживания
Индексы:
PRIMARY KEY, btree (airplane_code, seat_no)
Ограничения-проверки:
CHECK (fare_conditions IN ('Economy', 'Comfort', 'Business'))
Ограничения внешнего ключа:
FOREIGN KEY (airplane_code)
REFERENCES airplanes_data(airplane_code) ON DELETE CASCADE
Таблица bookings.segments
Перелёт соединяет билет с рейсом и идентифицируется их номерами.
Для каждого перелета указываются его стоимость (price
) и класс обслуживания (fare_conditions
).
Столбец | Тип | Допустимость NULL | Описание
-----------------+---------------+-------------------+---------------------
ticket_no | text | not null | Номер билета
flight_id | integer | not null | Идентификатор рейса
fare_conditions | text | not null | Класс обслуживания
price | numeric(10,2) | not null | Стоимость перелета
Индексы:
PRIMARY KEY, btree (ticket_no, flight_id)
btree (flight_id)
Ограничения-проверки:
CHECK (price >= 0)
CHECK (fare_conditions IN ('Economy', 'Comfort', 'Business'))
Ограничения внешнего ключа:
FOREIGN KEY (flight_id) REFERENCES flights(flight_id)
FOREIGN KEY (ticket_no) REFERENCES tickets(ticket_no)
Ссылки извне:
TABLE "boarding_passes" FOREIGN KEY (ticket_no, flight_id)
REFERENCES segments(ticket_no, flight_id)
Таблица bookings.tickets
Билет имеет уникальный номер (ticket_no
), состоящий из 13 цифр.
Билет содержит информацию о пассажире: номер документа, удостоверяющего личность (passenger_id
), а также его полное имя (passenger_name
). Номер документа состоит из кода страны и цифрового идентификатора, а полное имя — из имени и фамилии (имя указывается первым даже для тех стран, в которых принят обратный порядок, как, например, в Китае).
Для пассажира нет отдельной сущности, но пассажир однозначно идентифицируется номером документа. Гарантируется, что одному номеру документа всегда соответствует одно и то же имя пассажира (в разных документах имена могут совпадать). Один и тот же пассажир не может участвовать в одном бронировании несколько раз и не может следовать разными рейсами в одно и то же время (хотя последнее условие не проверяется на уровне базы данных).
Признак прямого билета (outbound
) имеет истинное значение для билета «туда» и ложное — для билета «обратно». Конечные пункты перелётов, включенных в прямой и обратный билеты, совпадают, но пути следования могут отличаться.
Столбец | Тип | Допустимость NULL | Описание
----------------+-------------+-------------------+-------------------------
ticket_no | text | not null | Номер билета
book_ref | char(6) | not null | Номер бронирования
passenger_id | text | not null | Номер документа
passenger_name | text | not null | Полное имя пассажира
outbound | boolean | not null | Является ли рейс прямым
Индексы:
PRIMARY KEY, btree (ticket_no)
UNIQUE CONSTRAINT, btree (book_ref, passenger_id, outbound)
Ограничения внешнего ключа:
FOREIGN KEY (book_ref) REFERENCES bookings(book_ref)
Ссылки извне:
TABLE "segments" FOREIGN KEY (ticket_no) REFERENCES tickets(ticket_no)
Представление bookings.timetable
Над таблицами routes
и flights
создано представление timetable
, скрывающее темпоральное соединение и добавляющее информацию о местном времени вылета и прибытия. Представление позволяет упростить многие запросы, что особенно важно для тех, кто только начинает изучать язык SQL. Однако применение этого представления в сложных запросах может ухудшить производительность из-за потенциально лишних соединений с таблицами аэропортов.
Столбец | Тип | Описание
---------------------------+-------------+--------------------------------------
flight_id | integer | Идентификатор рейса
route_no | text | Номер маршрута
departure_airport | char(3) | Код аэропорта отправления
arrival_airport | char(3) | Код аэропорта прибытия
status | status | Статус рейса
airplane_code | char(3) | Код самолёта, ИАТА
scheduled_departure | timestamptz | Время вылета по расписанию
scheduled_departure_local | timestamp | Время вылета по расписанию,
| | местное время в пункте отправления
actual_departure | timestamptz | Фактическое время вылета
actual_departure_local | timestamp | Фактическое время вылета,
| | местное время в пункте отправления
scheduled_arrival | timestamptz | Время прилёта по расписанию
scheduled_arrival_local | timestamp | Время прилёта по расписанию,
| | местное время в пункте прибытия
actual_arrival | timestamptz | Фактическое время прилёта
actual_arrival_local | timestamp | Фактическое время прилёта,
| | местное время в пункте прибытия
Определение представления:
SELECT f.flight_id,
f.flight_no,
r.departure_airport,
r.arrival_airport,
f.status,
r.airplane_code,
f.scheduled_departure,
(f.scheduled_departure AT TIME ZONE dep.timezone) AS scheduled_departure_local,
f.actual_departure,
(f.actual_departure AT TIME ZONE dep.timezone) AS actual_departure_local,
f.scheduled_arrival,
(f.scheduled_arrival AT TIME ZONE arr.timezone) AS scheduled_arrival_local,
f.actual_arrival,
(f.actual_arrival AT TIME ZONE arr.timezone) AS actual_arrival_local
FROM flights f
JOIN routes r ON r.flight_no = f.flight_no AND r.validity @> f.scheduled_departure
JOIN airports_data dep ON dep.airport_code = r.departure_airport
JOIN airports_data arr ON arr.airport_code = r.arrival_airport;
Функция bookings.now
Демонстрационная база содержит временной «срез» данных — так, как будто в некоторый момент была сделана резервная копия реальной системы. Например, если некоторый рейс имеет статус Departed
, это означает, что в момент резервного копирования самолёт вылетел и находился в воздухе.
Позиция «среза» сохранена в функции bookings.now
. Ей можно пользоваться в запросах там, где в обычной жизни использовалась бы функция now
.
Функция bookings.lang
Некоторые поля в демонстрационной базе содержат текст на английском и русском языках. Функция bookings.lang
возвращает значение параметра bookings.lang
, то есть язык, на котором будут выдаваться значения этих полей.
Эта функция используется в представлениях airplanes
и airports
и не предназначена для непосредственного использования в запросах.
Функция bookings.version
Функция bookings.version
возвращает версию демонстрационной базы данных. Версия состоит из названия воображаемой авиакомпании и даты начала авиаперевозок, а также сообщает охваченный интервал времени. Актуальная версия на текущий момент — PostgresPro 2025-09-01
.
Использование
По умолчанию значения различных переводимых полей выдаются на английском языке. Это поля airport_name
, city
и country
представления airports
, а также поле model
представления airplanes
.
Вы можете выбрать другой язык для отображения этих полей. Для переключения на русский (единственный перевод, представленный в данной базе) установите для параметра bookings.lang
значение ru
:
SET bookings.lang = 'ru';
Также может быть удобно выбрать язык на уровне базы данных:
ALTER DATABASE demo SET bookings.lang = 'ru';
Чтобы это изменение вступило в силу, необходимо повторно подключиться к базе данных.
Посмотрим на результаты нескольких простых запросов, чтобы лучше познакомиться с содержимым демонстрационной базы данных.
Результаты, представленные ниже, были получены для версии PostgresPro 2025-09-01 (91 days)
. Если в вашей системе запросы выдают другие данные, проверьте версию демонстрационной базы (функция bookings.version
). Незначительные отклонения могут быть связаны с местным временем, отличным от московского, и настройками локализации.
Все рейсы выполняются несколькими типами самолётов:
SELECT * FROM airplanes;
airplane_code | model | range | speed
---------------+------------------------+-------+-------
32N | Аэробус A320neo | 6500 | 830
339 | Аэробус A330-900neo | 13300 | 870
351 | Аэробус A350-1000 | 16700 | 913
35X | Аэробус A350F | 8700 | 903
76F | Боинг 767-300F | 6000 | 850
77W | Боинг 777-300ER | 14600 | 905
789 | Боинг 787-9 Dreamliner | 14000 | 913
7M7 | Боинг 737 MAX 7 | 7000 | 840
CR7 | Бомбардье CRJ700 | 3100 | 829
E70 | Эмбраэр E170 | 4000 | 800
(10 строк)
Для каждого типа самолёта хранится список мест в салоне. Например, вот где можно разместиться в бизнес-классе Эмбраэра E170:
SELECT *
FROM seats
WHERE airplane_code = 'E70' AND fare_conditions = 'Business';
airplane_code | seat_no | fare_conditions
---------------+---------+-----------------
E70 | 1A | Business
E70 | 1C | Business
E70 | 1D | Business
E70 | 2A | Business
E70 | 2C | Business
E70 | 2D | Business
(6 строк)
Самолёты большего размера имеют больше посадочных мест с разными классами обслуживания:
SELECT
s.airplane_code,
string_agg (s.fare_conditions || '(' || s.num || ')', ', ') as fare_conditions
FROM (
SELECT airplane_code, fare_conditions, count(*)::text as num
FROM seats
GROUP BY airplane_code, fare_conditions
) s
GROUP BY s.airplane_code
ORDER BY s.airplane_code;
airplane_code | fare_conditions
---------------+-----------------------------------------
32N | Business(28), Economy(138)
339 | Business(29), Economy(224), Comfort(28)
351 | Economy(281), Business(44)
77W | Economy(326), Business(30), Comfort(48)
789 | Economy(188), Business(48), Comfort(21)
7M7 | Business(16), Economy(144)
CR7 | Business(6), Economy(52), Comfort(12)
E70 | Business(6), Economy(72)
(8 строк)
Два типа самолётов (Аэробус A350F и Боинг 767-300F) являются грузовыми и не участвуют в пассажирских авиаперевозках.
База данных содержит список практически всех относительно крупных аэропортов:
SELECT
count(*) airports,
count(distinct country||','||city) cities,
count(distinct country) countries
FROM airports;
airports | cities | countries
----------+--------+-----------
5501 | 5157 | 230
(1 строка)
Например, к Москве относятся пять аэропортов:
SELECT airport_code, airport_name, coordinates, timezone
FROM airports
WHERE country = 'Россия' AND city = 'Москва';
airport_code | airport_name | coordinates | timezone
--------------+--------------+-------------------+---------------
BKA | Быково | (38.06,55.6172) | Europe/Moscow
DME | Домодедово | (37.9063,55.4088) | Europe/Moscow
OSF | Остафьево | (37.5072,55.5117) | Europe/Moscow
SVO | Шереметьево | (37.4146,55.9726) | Europe/Moscow
VKO | Внуково | (37.2615,55.5915) | Europe/Moscow
(5 rows)
Маршрутная сеть хранится в таблице routes
. Вот, например, куда, в какие дни недели и за какое время можно долететь из Рима первого ноября 2025 года:
SELECT r.route_no, a.airport_code, a.airport_name, a.city, a.country, r.days_of_week, r.duration
FROM routes r
JOIN airports a ON a.airport_code = r.arrival_airport
WHERE departure_airport = (SELECT airport_code FROM airports WHERE airport_name = 'Фьюмичино')
AND validity @> '2025-11-01 00:00:00CET'::timestamptz;
route_no | airport_code | airport_name | city | country | days_of_week | duration
----------+--------------+--------------+---------+-------------------+-----------------+----------
PG0086 | BGY | Бергамо | Милан | Италия | {1,2,3,4,5,6,7} | 01:05:00
PG0176 | ORY | Орли | Париж | Франция | {2,4,6,7} | 01:55:00
PG0228 | HGH | Сяошань | Ханчжоу | Китай | {7} | 11:30:00
PG0233 | MXP | Мальпенса | Милан | Италия | {1,2,3,4,5,6,7} | 01:05:00
PG0235 | ORD | О'Хара | Чикаго | Соединенные Штаты | {2} | 09:50:00
(5 строк)
Обратите внимание, что время указано в часовом поясе аэропорта вылета (CET, Central European Time).
База данных была сформирована на момент, возвращаемый функцией bookings.now
:
SELECT bookings.now();
now
------------------------
2025-12-01 00:00:00+03
(1 строка)
Относительно именно этого момента все рейсы делятся на прошедшие и будущие.
SELECT
status,
count(*) as count,
min(scheduled_departure) as min_scheduled_departure,
max(scheduled_departure) as max_scheduled_departure
FROM flights
GROUP BY status
ORDER BY min_scheduled_departure;
status | count | min_scheduled_departure | max_scheduled_departure
-----------+-------+-------------------------+-------------------------
Arrived | 10966 | 2025-10-01 03:00:00+03 | 2025-12-01 02:10:00+03
Cancelled | 121 | 2025-10-01 15:25:00+03 | 2026-01-29 19:20:00+03
Departed | 20 | 2025-11-30 15:50:00+03 | 2025-12-01 02:50:00+03
Boarding | 4 | 2025-12-01 02:55:00+03 | 2025-12-01 03:25:00+03
Delayed | 10 | 2025-12-01 03:30:00+03 | 2025-12-02 01:00:00+03
On Time | 157 | 2025-12-01 03:35:00+03 | 2025-12-02 02:55:00+03
Scheduled | 10480 | 2025-12-02 03:10:00+03 | 2026-01-30 02:55:00+03
(7 строк)
Найдем ближайший рейс, вылетающий из Екатеринбурга (аэропорт SVX
) в Ухань (аэропорт WUH
). Воспользуемся представлением timetable
, чтобы не соединять таблицы routes
и flights
:
SELECT *
FROM timetable t
WHERE t.departure_airport = 'SVX'
AND t.arrival_airport = 'WUH'
AND t.scheduled_departure > bookings.now()
ORDER BY t.scheduled_departure
LIMIT 1 \gx
-[ RECORD 1 ]-------------+-----------------------
flight_id | 11465
route_no | PG0522
departure_airport | SVX
arrival_airport | WUH
status | Scheduled
airplane_code | 7M7
scheduled_departure | 2025-12-03 10:30:00+03
scheduled_departure_local | 2025-12-03 12:30:00
actual_departure |
actual_departure_local |
scheduled_arrival | 2025-12-03 17:30:00+03
scheduled_arrival_local | 2025-12-03 22:30:00
actual_arrival |
actual_arrival_local |
Обратите внимание, что в представлении timetable
указано не только локальное (московское) время, но и местное время в аэропортах вылета и прилёта.
Каждое бронирование может включать несколько билетов, по одному на каждого пассажира. Билет, в свою очередь, может включать несколько перелётов. Полная информация о бронировании находится в трёх таблицах: bookings
, tickets
и segments
.
Посмотрим на бронирование с кодом JU35I4
:
SELECT * FROM bookings WHERE book_ref = 'JU35I4';
book_ref | book_date | total_amount
----------+-------------------------------+--------------
JU35I4 | 2025-10-09 06:53:16.710703+03 | 86750.00
(1 строка)
Вот из каких билетов оно состоит:
SELECT *
FROM tickets
WHERE book_ref = 'JU35I4';
ticket_no | book_ref | passenger_id | passenger_name | outbound
---------------+----------+------------------+-------------------+----------
0005433348362 | JU35I4 | RU 2714075620824 | Nadezhda Sergeeva | t
0005433348356 | JU35I4 | RU 8692103212506 | Artur Isakov | t
(2 строки)
Как мы видим, в бронирование входят билеты двух пассажиров. Узнаем, какие перелёты включены в билет Надежды Сергеевой:
SELECT r.route_no,
dep.airport_code dep_airport, dep.country dep_country, dep.city dep_city,
arr.airport_code arr_airport, arr.country arr_country, arr.city arr_city
FROM segments s
JOIN flights f ON f.flight_id = s.flight_id
JOIN routes r ON r.route_no = f.route_no AND r.validity @> f.scheduled_departure
JOIN airports dep ON dep.airport_code = r.departure_airport
JOIN airports arr ON arr.airport_code = r.arrival_airport
WHERE s.ticket_no = '0005433348362'
ORDER BY f.scheduled_departure;
route_no | dep_airport | dep_country | dep_city | arr_airport | arr_country | arr_city
----------+-------------+-------------+--------------------+-------------+-------------+--------------------
PG0370 | OVB | Россия | Новосибирск | SVO | Россия | Москва
PG0179 | SVO | Россия | Москва | FRA | Германия | Франкфурт-на-Майне
PG0408 | FRA | Германия | Франкфурт-на-Майне | FCO | Италия | Рим
PG0482 | FCO | Италия | Рим | HEL | Финляндия | Хельсинки
(3 строки)
Как видим, Наталья летит из Новосибирска в Хельсенки с пересадками в Москвве, Франкфурте-на-Майне и Риме.
Часть перелётов в этом билете уже выполнены на момент, возвращаемый функцией bookings.now
, а часть — ещё нет. После регистрации на первый рейс пассажиру выдаются посадочные талоны с указанием мест. В первых двух посадочных талонах Надежды указаны номер и время посадки в самолёт, а на следующие два рейса посадка ещё предстоит:
SELECT f.route_no, f.flight_id, f.status, bp.seat_no, bp.boarding_no, bp.boarding_time
FROM flights f
JOIN boarding_passes bp ON bp.flight_id = f.flight_id
WHERE bp.ticket_no = '0005433348362'
ORDER BY f.scheduled_departure;
route_no | flight_id | status | seat_no | boarding_no | boarding_time
----------+-----------+-----------+---------+-------------+-------------------------------
PG0370 | 10817 | Arrived | 17B | 45 | 2025-11-29 18:18:42.972147+03
PG0179 | 10935 | Arrived | 16A | 33 | 2025-11-30 11:54:41.297034+03
PG0408 | 11108 | On Time | 24C | |
PG0482 | 11264 | Scheduled | 4B | |
(4 строки)
Надеемся, что эти несколько простых примеров помогли составить представление о содержимом демонстрационной базы данных.
Версия от 15.08.2017

Файлы
- demo-small.zip (21 МБ) — данные по полетам за один месяц (размер БД примерно 300 МБ),
- demo-medium.zip (62 МБ) — данные по полетам за три месяца (размер БД примерно 700 МБ),
- demo-big.zip (232 МБ) — данные по полетам за год (размер БД примерно 2,5 ГБ).
Описание
Отличия от предыдущей версии
- Таблица
airports
заменена на одноименное представление над таблицейairports_data
, в которой поляairport_name
иcity
содержат значения как на русском, так и на английском языках. Представление показывает данные на языке, установленном в конфигурационном параметреbookings.lang
(по умолчанию — русский). - Аналогично таблица
aircrafts
заменена на одноименное представление над таблицейaircrafts_data
. Переведено полеmodel
. - Материализованное представление
routes
заменено на обычное, чтобы не требовалось обновление при изменении параметраbookings.lang
. - В представлении
airports
и таблицеairports_data
поляlongitude
иlatitude
заменены на одно полеcoordinates
типаpoint
. - При подключении к демонстрационной базе данных правильное значение параметра
search_path
устанавливается автоматически.
Версия от 13.10.2016
Файлы
- demo-small-20161013.zip (21 МБ) — данные по полетам за один месяц (размер БД примерно 300 МБ),
- demo-medium-20161013.zip (62 МБ) — данные по полетам за три месяца (размер БД примерно 700 МБ),
- demo-big-20161013.zip (232 МБ) — данные по полетам за год (размер БД примерно 2,5 ГБ).
Описание
То же самое одним PDF-файлом.