Travel plans 🚂
Scenario
You're helping a client plan a trip from New York to Paris, and they want you to find the fastest and cheapest routes.
They have collected journey information for routes that they are happy to take into two tables:
routes_timetable
routes_schedule
The timetable table records individual routes with their full departure/arrival timestamps and cost. The schedule table records the schedule of repeated routes with their schedule definition.
The earliest they can leave from New York is 2024-01-01 12:00:00-05:00
.
Question
Given the tables that your client has provided, find the fastest and cheapest route from New York to Paris, leaving after 2024-01-01 12:00:00-05:00
.
Give a minimum of 30 minutes and a maximum of 6 hours for "interchange" time, which is the time between arrival and departure at the same location. All costs are in the same currency (with no currency specified by the client).
The output should have at most two rows (the fastest/cheapest routes, which may be the same route), with the columns:
route
which is each location in the route separated by a hyphen, e.g.New York - London - Paris
departure_datetime_utc
as the departure time (UTC) from New Yorkarrival_datetime_utc
as the arrival time (UTC) in Parisduration
as the total duration of the journeycost
as the total cost of the journey
Order the output by arrival_datetime_utc
.
Expand for the DDL
create table routes_schedule (
schedule_id int primary key,
mode_of_transport varchar not null,
from_location varchar not null,
to_location varchar not null,
earliest_departure timetz not null,
latest_departure timetz not null,
frequency time, /* `null` means that it's daily */
duration time not null,
cost decimal(8, 2) not null,
);
insert into routes_schedule
values
(1, 'train', 'London St Pancras', 'London Gatwick', '08:00:00+00:00', '20:00:00+00:00', '01:00:00', '00:30:00', 17.50),
(2, 'train', 'London St Pancras', 'London Gatwick', '07:30:00+00:00', '22:30:00+00:00', '02:30:00', '01:15:00', 12.00),
(3, 'bus', 'London St Pancras', 'London Gatwick', '06:15:00+00:00', '06:15:00+00:00', null, '03:30:00', 6.75),
(4, 'bus', 'London St Pancras', 'London Gatwick', '19:30:00+00:00', '19:30:00+00:00', null, '03:30:00', 6.75),
(5, 'train', 'London Gatwick', 'London St Pancras', '09:00:00+00:00', '21:00:00+00:00', '01:00:00', '00:30:00', 17.50),
(6, 'train', 'London Gatwick', 'London St Pancras', '07:15:00+00:00', '22:15:00+00:00', '02:30:00', '01:15:00', 12.00),
(7, 'bus', 'London Gatwick', 'London St Pancras', '06:00:00+00:00', '06:00:00+00:00', null, '03:30:00', 6.75),
(8, 'bus', 'London Gatwick', 'London St Pancras', '20:00:00+00:00', '20:00:00+00:00', null, '03:30:00', 6.75)
;
create table routes_timetable (
route_id int primary key,
mode_of_transport varchar not null,
from_location varchar not null,
to_location varchar not null,
departure_datetime timestamptz not null,
arrival_datetime timestamptz not null,
cost decimal(8, 2) not null,
);
insert into routes_timetable
values
(1, 'boat', 'London St Pancras', 'Paris', '2024-01-01 06:00:00+00:00', '2024-01-01 07:30:00+01:00', 45.00),
(2, 'plane', 'London Gatwick', 'New York', '2024-01-01 13:05:00+00:00', '2024-01-01 20:55:00-05:00', 158.00),
(3, 'plane', 'London Gatwick', 'New York', '2024-01-02 20:40:00+00:00', '2024-01-03 04:30:00-05:00', 147.00),
(4, 'plane', 'London St Pancras', 'Paris', '2024-01-03 07:00:00+00:00', '2024-01-03 08:30:00+01:00', 70.00),
(5, 'plane', 'Paris', 'New York', '2024-01-02 12:00:00+01:00', '2024-01-02 20:30:00-05:00', 180.00),
(6, 'plane', 'New York', 'London Gatwick', '2024-01-01 13:00:00-05:00', '2024-01-02 05:45:00+00:00', 160.00),
(7, 'boat', 'New York', 'London Gatwick', '2024-01-01 05:30:00-05:00', '2024-01-01 23:00:00+00:00', 195.00),
(8, 'boat', 'London St Pancras', 'Paris', '2024-01-01 18:00:00+00:00', '2024-01-01 19:30:00+01:00', 95.00),
(9, 'boat', 'London St Pancras', 'Paris', '2024-01-02 14:00:00+00:00', '2024-01-02 15:30:00+01:00', 40.00),
(10, 'plane', 'New York', 'Paris', '2024-01-01 18:00:00-05:00', '2024-01-02 17:45:00+01:00', 279.00)
;
The solution can be found at:
Sample input
Routes Schedule
schedule_id | mode_of_transport | from_location | to_location | earliest_departure | latest_departure | frequency | duration | cost |
---|---|---|---|---|---|---|---|---|
1 | train | London Gatwick | London St Pancras | 09:00:00 +00:00 | 21:00:00 +00:00 | 01:00:00 | 00:30:00 | 12.25 |
2 | bus | London Gatwick | London St Pancras | 06:00:00 +00:00 | 06:00:00 +00:00 | null | 03:30:00 | 8.50 |
Routes Timetable
route_id | mode_of_transport | from_location | to_location | departure_datetime | arrival_datetime | cost |
---|---|---|---|---|---|---|
1 | boat | New York | London Gatwick | 2024-01-01T09:30Z | 2024-01-01T22:00Z | 179.00 |
2 | plane | New York | London Gatwick | 2024-01-01T23:00Z | 2024-01-02T10:45Z | 125.00 |
3 | boat | London St Pancras | Paris | 2024-01-02T13:00Z | 2024-01-02T13:30Z | 75.00 |
with
routes_schedule(
schedule_id,
mode_of_transport,
from_location,
to_location,
earliest_departure,
latest_departure,
frequency,
duration,
cost
) as (
values
(1, 'train', 'London Gatwick', 'London St Pancras', '09:00:00+00:00'::timetz, '21:00:00+00:00'::timetz, '01:00:00'::time, '00:30:00'::time, 12.25),
(2, 'bus', 'London Gatwick', 'London St Pancras', '06:00:00+00:00'::timetz, '06:00:00+00:00'::timetz, null::time, '03:30:00'::time, 8.50)
),
routes_timetable(
route_id,
mode_of_transport,
from_location,
to_location,
departure_datetime,
arrival_datetime,
cost
) as (
values
(1, 'boat', 'New York', 'London Gatwick', '2024-01-01 04:30:00-05:00'::timestamptz, '2024-01-01 22:00:00+00:00'::timestamptz, 179.00),
(2, 'plane', 'New York', 'London Gatwick', '2024-01-01 18:00:00-05:00'::timestamptz, '2024-01-02 10:45:00+00:00'::timestamptz, 125.00),
(3, 'boat', 'London St Pancras', 'Paris', '2024-01-02 13:00:00+00:00'::timestamptz, '2024-01-02 14:30:00+01:00'::timestamptz, 75.00)
)
Sample output
route | departure_datetime_utc | arrival_datetime_utc | duration | cost |
---|---|---|---|---|
New York - London Gatwick - London St Pancras - Paris | 2024-01-01 23:00:00 | 2024-01-02 13:30:00 | 14:30:00 | 212.25 |
solution(route, departure_datetime_utc, arrival_datetime_utc, duration, cost) as (
values
('New York - London Gatwick - London St Pancras - Paris', '2024-01-01 23:00:00'::timestamp, '2024-01-02 13:30:00'::timestamp, '14:30:00', 212.25);
)
Hint 1
Expand the routes_schedule
table into individual routes and then union with the routes_timetable
table for a full list of routes to consider.
Hint 2
Use a recursive CTE to build up the journey from New York to Paris, considering the interchange time between routes.