M.5. Usage

M.5.1. Translations

By default, values of several translatable fields are shown in English. These are airport_name, city, and coutry of the airports view, as well as model of the airplanes view.

You can choose to display these fields in Russian (the only translation provided in the demo database). To switch to Russian, set the bookings.lang parameter to ru:

SET bookings.lang = 'ru';

or

ALTER DATABASE demo SET bookings.lang = 'ru';

You have to reconnect to the database for this command to take effect.

M.5.2. Sample Queries

To better understand the contents of the demo database, let's take a look at the results of several simple queries.

The results displayed below were received on a small database version PostgresPro 2025-09-01 (91 days). If the same queries return different data on your system, check your demo database version (using the bookings.version function). Some minor deviations may be caused by the difference between your local time and Moscow time, or your locale settings.

All flights are operated by several types of airplanes:

SELECT * FROM airplanes;
 airplane_code |         model          | range | speed
---------------+------------------------+-------+-------
 32N           | Airbus A320neo          |  6500 |   830
 339           | Airbus A330-900neo      | 13300 |   870
 351           | Airbus A350-1000        | 16700 |   913
 35X           | Airbus A350F            |  8700 |   903
 76F           | Boeing 767-300F         |  6000 |   850
 77W           | Boeing 777-300ER        | 14600 |   905
 789           | Boeing 787-9 Dreamliner | 14000 |   913
 7M7           | Boeing 737 MAX 7        |  7000 |   840
 CR7           | Bombardier CRJ700       |  3100 |   829
 E70           | Embraer E170            |  4000 |   800
(10 rows)
    

For each airplane type, a separate list of seats is supported. For example, in Embraer E170 business class, one can select the following seats:

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 rows)
    

Bigger airplanes have more seats of various travel classes:

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 rows)
    

Airbus A350F and Boeing 767-300F are cargo modifications and are not serving routes.

The demo database contains the list of airports of almost all major airports. Most cities have only one airport.

    SELECT
    count(*) airports,
    count(distinct country||','||city) cities,
    count(distinct country) countries
FROM airports;
 airports | cities | countries
----------+--------+-----------
     5501 |   5157 |       230
(1 row)

For example, Moscow has five airports:

SELECT airport_code, airport_name, coordinates, timezone
FROM airports
WHERE country = 'Russia' AND city = 'Moscow';
 airport_code | airport_name |    coordinates    |   timezone
--------------+--------------+-------------------+---------------
 BKA          | Bykovo       | (38.06,55.6172)   | Europe/Moscow
 DME          | Domodedovo   | (37.9063,55.4088) | Europe/Moscow
 OSF          | Ostafyevo    | (37.5072,55.5117) | Europe/Moscow
 SVO          | Sheremetyevo | (37.4146,55.9726) | Europe/Moscow
 VKO          | Vnukovo      | (37.2615,55.5915) | Europe/Moscow
(5 rows)

The routing map is stored in the routes table. For example, here are the destinations where you can get from Rome on November, 1, 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 =
 'Fiumicino')
    AND validity @> '2025-11-01 00:00:00CET'::timestamptz;
 route_no | airport_code | airport_name |   city   |    country    |  days_of_week   | duration 
----------+--------------+--------------+----------+---------------+-----------------+----------
 PG0086   | BGY          | Bergamo      | Milan    | Italy         | {1,2,3,4,5,6,7} | 01:05:00
 PG0176   | ORY          | Orly         | Paris    | France        | {2,4,6,7}       | 01:55:00
 PG0228   | HGH          | Xiaoshan     | Hangzhou | China         | {7}             | 11:30:00
 PG0233   | MXP          | Malpensa     | Milan    | Italy         | {1,2,3,4,5,6,7} | 01:05:00
 PG0235   | ORD          | O'Hare       | Chicago  | United States | {2}             | 09:50:00
(5 rows)
    

Mind that the timezone is CET, Central European Time.

The database was formed at the moment returned by the bookings.now() function:

SELECT bookings.now();
          now
------------------------
 2025-12-01 00:00:00+03
(1 row)
    

In relation to this moment, all flights are classified as past and future flights:

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 rows)
    

Let's find the next flight from Yekaterinburg (SVX airport) to Wuhan (WUH airport). Let's use the timetable view to avoid joining flights and routes tables:

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      |
    

Mind that two types of time are presented: local (Moscow) time and local time of the destination airport.

M.5.3. Bookings

Each booking can include several tickets, one for each passenger. The ticket, in its turn, can include several flight segments. The complete information about the booking is stored in three tables: bookings, tickets, and segments.

Let's take a look at the booking with code 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 row)
    

It contains the following tickets:

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 rows)
    

If we would like to know, which flight segments are included into Nadezhda Sergeeva's ticket, we can use the following query:

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         | Russia      | Novosibirsk        | SVO         | Russia      | Moscow
 PG0179   | SVO         | Russia      | Moscow             | FRA         | Germany     | Frankfurt am Main
 PG0408   | FRA         | Germany     | Frankfurt am Main  | FCO         | Italy       | Rome
 PG0482   | FCO         | Italy       | Rome               | HEL         | Finland     | Helsinki
 (3 rows)
    

As we can see, Nadezhda flies from Novosibirsk to Helsinki with transfers in Moscow, Frankfurt am Main, and Rome.

Some of the flight segments in this ticket have earlier dates than the bookings.now() return value: it means that these flights had already happened. After the registration to the first flight, the passenger receives boarding passes with seat numbers. The first two boarding passes of Nadezhda have the number and the boarding time, while for the last two boarding passes the boarding is yet to come:

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 rows)
    

We hope that these simple examples helped you get an idea of this demo database.