Bookings database: airline schema, tables and SQL exercises
Bookings is the PostgreSQL demo database of an airline: flights between 104 airports, bookings, tickets and boarding passes. On SQLtest.online you can query it right in your browser: solve exercises with automatic checking and run your own queries in the playground, with nothing to install.
- 8 tables and 4 views
- 33,121 flights
- 1,045,726 tickets × flights
- 52 SQL exercises
What is Bookings
Bookings is the demo database that Postgres Professional publishes for learning PostgreSQL. It models the flights of a Russian airline: routes, aircraft and their seat maps, bookings, tickets and boarding passes.
This copy holds flights from July to September 2017. Airport and aircraft names are stored as JSONB in English and Russian, and airport coordinates use the PostgreSQL point type, so the database is good for practicing PostgreSQL-specific SQL as well as JOINs and analytics on large tables.
ER diagram
The diagram shows the Bookings tables and the foreign keys between them. Click it to open the full-size version.
What's inside
The tables fall into two groups.
Reference data
airports_data, aircrafts_data and seats: the seat map of each aircraft model.
Sales and flights
bookings → tickets → ticket_flights ← flights, plus boarding_passes issued at check-in.
The key thing to remember: one booking can include several passengers, and one ticket can cover several flights. The link between tickets and flights is ticket_flights, the largest table. The views aircrafts, airports, flights_v and routes show the same data in a friendlier form.
How much data the tables hold:
| Table | Rows | Contents |
|---|---|---|
| bookings | 262,788 | bookings |
| tickets | 366,733 | tickets, one per passenger |
| ticket_flights | 1,045,726 | flight segments of tickets |
| boarding_passes | 579,686 | boarding passes |
| flights | 33,121 | scheduled and performed flights |
| airports_data | 104 | airports |
| aircrafts_data | 9 | aircraft models |
| seats | 1,339 | seats by aircraft model |
Table structure
Click a table to see its columns, a sample row and its keys.
The list of tables
- aircraft_codeUnique code for each aircraft
- modelAircraft model name in English and Russian in JSON format
- rangeAircraft fly range in kilometers
- PRIMARY KEY, btree (aircraft_code)
| aircraft_code | model | range | |
|---|---|---|---|
| 1 | 773 | {"en": "Boeing 777-300", "ru": "Боинг 777-300"} | 11100 |
- airport_codeUnique code for each airport
- airport_nameAirport name in English and Russian in JSON format
- cityAirport city in English and Russian in JSON format
- coordinatesAirport coordinates as POINT(longitude, latitude)
- timezoneAirport timezone name
- PRIMARY KEY, btree (airport_code)
| airport_code | airport_name | city | coordinates | timezone | |
|---|---|---|---|---|---|
| 1 | YKS | {"en": "Yakutsk Airport", "ru": "Якутск"} | {"en": "Yakutsk", "ru": "Якутск"} | (129.77099609375,62.0932998657227) | Asia/Yakutsk |
- ticket_noTicket number
- flight_idFlight identificator
- boarding_noBoarding pass number
- seat_noSeat number
- 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)
| ticket_no | flight_id | boarding_no | seat_no | |
|---|---|---|---|---|
| 1 | 0005435212351 | 30625 | 1 | 2D |
- book_refBooking number
- book_dateBooking date
- total_amountTotal booking cost
- PRIMARY KEY, btree (book_ref)
| book_ref | book_date | total_amount | |
|---|---|---|---|
| 1 | 00000F | 2017-07-05 00:12:00+00 | 265700.00 |
- flight_idFlight ID
- flight_noFlight number
- scheduled_departureScheduled departure time
- scheduled_arrivalScheduled arrival time
- departure_airportAirport of departure
- arrival_airportAirport of arrival
- statusFlight status
- aircraft_codeAircraft code, IATA
- actual_departureActual departure time
- actual_arrivalActual arrival time
- PRIMARY KEY, btree (flight_id)
- UNIQUE CONSTRAINT, btree (flight_no, scheduled_departure)
| flight_id | flight_no | scheduled_departure | scheduled_arrival | departure_airport | arrival_airport | status | aircraft_code | actual_departure | actual_arrival | |
|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 1185 | PG0134 | 2017-09-10 06:50:00+00 | 2017-09-10 11:55:00+00 | DME | BTK | Scheduled | 319 |
- aircraft_codeAircraft code, IATA
- seat_noSeat number
- fare_conditionsTravel class
- PRIMARY KEY, btree (aircraft_code, seat_no)
- FOREIGN KEY (aircraft_code) REFERENCES aircrafts(aircraft_code) ON DELETE CASCADE
| aircraft_code | seat_no | fare_conditions | |
|---|---|---|---|
| 1 | 319 | 2A | Business |
- ticket_noTicket number
- flight_idFlight ID
- fare_conditionsTravel class
- amountTravel cost
- PRIMARY KEY, btree (ticket_no, flight_id)
- FOREIGN KEY (flight_id) REFERENCES flights(flight_id)
- FOREIGN KEY (ticket_no) REFERENCES tickets(ticket_no)
| ticket_no | flight_id | fare_conditions | amount | |
|---|---|---|---|---|
| 1 | 0005432159776 | 30625 | Business | 42100.00 |
- ticket_noTicket number
- book_refBooking number
- passenger_idPassenger ID
- passenger_namePassenger name
- contact_dataPassenger contact information
| ticket_no | book_ref | passenger_id | passenger_name | contact_data | |
|---|---|---|---|---|---|
| 1 | 0005432000987 | 06B046 | 8149 604011 | VALERIY TIKHONOV | {"phone": "+70127117011"} |
- PRIMARY KEY, btree (ticket_no)
- FOREIGN KEY (book_ref) REFERENCES bookings(book_ref)
Sample queries
These queries show how the data is connected. Copy any of them and run it in the playground.
A ticket and its booking: the passenger and the booking amount.
SELECT t.ticket_no, t.passenger_name, b.book_date, b.total_amount
FROM tickets t
JOIN bookings b ON b.book_ref = t.book_ref
ORDER BY t.ticket_no
LIMIT 3;
| ticket_no | passenger_name | book_date | total_amount |
|---|---|---|---|
| 0005432000987 | VALERIY TIKHONOV | 2017-07-05 17:19:00+00 | 12400.00 |
| 0005432000988 | EVGENIYA ALEKSEEVA | 2017-07-05 17:19:00+00 | 12400.00 |
| 0005432000989 | ARTUR GERASIMOV | 2017-06-28 22:55:00+00 | 24700.00 |
A flight and its aircraft: reading an English name from a JSONB column with ->>.
SELECT f.flight_no, f.departure_airport, f.arrival_airport,
a.model ->> 'en' AS aircraft
FROM flights f
JOIN aircrafts_data a ON a.aircraft_code = f.aircraft_code
ORDER BY f.flight_id
LIMIT 3;
| flight_no | departure_airport | arrival_airport | aircraft |
|---|---|---|---|
| PG0405 | DME | LED | Airbus A321-200 |
| PG0404 | DME | LED | Airbus A321-200 |
| PG0405 | DME | LED | Airbus A321-200 |
Fare and seat: from a ticket segment to its flight and boarding pass. The LEFT JOIN keeps segments without a boarding pass.
SELECT tf.ticket_no, f.flight_no, tf.fare_conditions, tf.amount, bp.seat_no
FROM ticket_flights tf
JOIN flights f ON f.flight_id = tf.flight_id
LEFT JOIN boarding_passes bp
ON bp.ticket_no = tf.ticket_no AND bp.flight_id = tf.flight_id
ORDER BY tf.ticket_no, f.flight_id
LIMIT 3;
| ticket_no | flight_no | fare_conditions | amount | seat_no |
|---|---|---|---|---|
| 0005432000987 | PG0242 | Economy | 6200.00 | 7A |
| 0005432000988 | PG0242 | Economy | 6200.00 | 10E |
| 0005432000989 | PG0242 | Economy | 6200.00 | 18E |
SQL exercises by topic
There are 52 exercises on the Bookings database, from simple lookups to analytics over a million rows. Solutions are checked automatically on a real PostgreSQL server. The number on the right is how many exercises a topic has; the colored dots show its difficulty range.
Where to start
The first exercises on the Bookings database:
- Get airports data
- Airports List
- Long-Range Aircrafts
- Find Boeing aircraft
- Flights Departed from Domodedovo
- List Aircraft from Domodedovo
- Get Bookings by Date
- Aircraft usage analysis
- Fare Conditions Types
- Aircraft Lacking Business Class Seats
FAQ
Do I need to install PostgreSQL to use the Bookings database?
No. The exercises and the playground on SQLtest.online run your queries on our servers, so a browser is all you need. In the playground, Bookings is available on PostgreSQL 18.
Where can I download the Bookings demo database?
Postgres Professional publishes it in several sizes on its website, together with a description of the schema.
Why are some names in curly braces?
Airport, city and aircraft names are JSONB objects with English and Russian values. Use ->> 'en' to get the English text, or query the views, which pick one language.