如何获得每辆经过停靠站的公交车的下 2 个停靠时间(GTFS 数据)?
How can I get the next 2 stop times for each bus that passes a stop (GTFS data)?
我的目标很简单。在我的应用程序中,用户按下停靠站,它会打开一个屏幕,显示经过该停靠站的每条路线(公共汽车),并显示该停靠站每条路线的下 2 次停靠时间。当用户按下停止 ID 为 1571 的停止时我要显示的内容示例:
公交车停靠 569
路线 2
23 分钟(上午 7:23)
43 分钟(上午 7:43)
37 号公路
15 分钟(早上 7:15)
45 分钟(早上 7:45)
返回的示例数据(我想要的):
st.departure_time, rte.route_long_name, tr.trip_headsign
07:23:00,2 号公路,市区
07:43:00,2 号公路,市区
07:15:00,37 号公路,市区
07:45:00,37 号公路,市区
应注意停止代码为 569,停止 ID 为 1571。根据 GTFS 文档,用户通常会搜索停止代码 (569),但在内部搜索停止 ID (1571)是搜索的内容。这些来自 GTFS 包中的 stops.txt 文件。
该示例显示了 2 条路线(2 和 37),但可能有更多路线,可能只有 1 条路线,或者在不久的将来根本没有路线经过此站点(我想忽略超过 24 小时的时间)。
免责声明:我不太擅长SQL。我能够创建一个似乎可以检索相关数据的查询,但是,它 returns 比每条路线的下 2 个停靠时间多得多的数据。我正在我的应用程序中解析它以获得所需的结果,但我觉得只改进我的查询会容易得多。
SELECT stop_times.departure_time, routes.route_long_name, trips.trip_headsign, calendar.monday, calendar.tuesday, calendar.wednesday, calendar.thursday, calendar.friday, calendar.saturday, calendar.sunday
FROM stop_times, trips, routes, calendar
WHERE stop_times.stop_id = '1571' AND stop_times.trip_id = trips.trip_id AND trips.route_id = routes.route_id AND trips.service_id = calendar.service_id AND 20180801 >= calendar.start_date AND 20180801 <= calendar.end_date
ORDER BY routes.route_short_name, trips.service_id, stop_times.departure_time
这是相关的表格。我完全按照 GTFS 文档中指定的方式将数据存储在数据库中。
stops.txt example rows:
routes.txt example rows:
trips.txt 示例行:
stop_times.txt 示例行:
calendar.txt 示例行:
非常感谢您的帮助。
您已经可以做的事情之一是使用标准的 JOIN 表示法。
它更具可读性,并且不太容易导致意外的笛卡尔连接。
并且使用短别名可以使 SQL 更简洁。
SET @StopId = '1571';
SET @CalDate = cast('2018-08-01' as date);
SELECT
st.departure_time,
rte.route_long_name,
tr.trip_headsign,
cal.monday, cal.tuesday, cal.wednesday, cal.thursday, cal.friday,
cal.saturday, cal.sunday
FROM stop_times AS st
JOIN trips AS tr ON tr.trip_id = st.trip_id
JOIN routes AS rte ON rte.route_id = tr.route_id
JOIN calendar AS cal ON cal.service_id = tr.service_id
WHERE st.stop_id = @StopId
AND @CalDate between cal.start_date and cal.end_date
ORDER BY rte.route_short_name, tr.service_id, st.departure_time
至于每条路线获得接下来 2 站的要求?
这里有一个例子 SQL。
它包括工作日的支票。不确定是否需要,所以这只是为了演示。
一个SQLFiddle因为可以找到here
SET @StopId = 1571;
SET @CalDate = cast('2018-08-01' as date);
SET @StartTime = cast('08:00:00' as time);
SELECT departure_time, route_long_name, trip_headsign
FROM
(
SELECT
st.departure_time,
tr.service_id,
rte.route_short_name,
rte.route_long_name,
tr.trip_headsign,
@num := if(@prev_routeid = tr.route_id, @num + 1, 1) as RN,
@prev_routeid := tr.route_id as route_id
FROM stop_times AS st
JOIN trips AS tr ON tr.trip_id = st.trip_id
JOIN routes AS rte ON rte.route_id = tr.route_id
JOIN calendar AS cal ON cal.service_id = tr.service_id
-- LEFT JOIN stops AS s on s.stop_id = st.stop_id
CROSS JOIN (SELECT @num := 0, @type := '') AS vars
WHERE st.stop_id = @StopId
AND @CalDate between cal.start_date and cal.end_date
AND (CASE WEEKDAY(@CalDate)
WHEN 0 THEN monday
WHEN 1 THEN tuesday
WHEN 2 THEN wednesday
WHEN 3 THEN thursday
WHEN 4 THEN friday
WHEN 5 THEN saturday
WHEN 6 THEN sunday
END) = 1
AND st.departure_time >= @StartTime
ORDER BY tr.route_id, st.departure_time
) Q
WHERE RN <= 2
ORDER BY route_short_name, service_id, departure_time;
旁注:
RN 是使用变量以旧的 MySql 7 样式计算的。
在 MySql 8 中,可以使用 window 函数 ROW_NUMBER 代替。
我的目标很简单。在我的应用程序中,用户按下停靠站,它会打开一个屏幕,显示经过该停靠站的每条路线(公共汽车),并显示该停靠站每条路线的下 2 次停靠时间。当用户按下停止 ID 为 1571 的停止时我要显示的内容示例:
公交车停靠 569
路线 2
23 分钟(上午 7:23)
43 分钟(上午 7:43)
37 号公路
15 分钟(早上 7:15)
45 分钟(早上 7:45)
返回的示例数据(我想要的):
st.departure_time, rte.route_long_name, tr.trip_headsign
07:23:00,2 号公路,市区
07:43:00,2 号公路,市区
07:15:00,37 号公路,市区
07:45:00,37 号公路,市区
应注意停止代码为 569,停止 ID 为 1571。根据 GTFS 文档,用户通常会搜索停止代码 (569),但在内部搜索停止 ID (1571)是搜索的内容。这些来自 GTFS 包中的 stops.txt 文件。
该示例显示了 2 条路线(2 和 37),但可能有更多路线,可能只有 1 条路线,或者在不久的将来根本没有路线经过此站点(我想忽略超过 24 小时的时间)。
免责声明:我不太擅长SQL。我能够创建一个似乎可以检索相关数据的查询,但是,它 returns 比每条路线的下 2 个停靠时间多得多的数据。我正在我的应用程序中解析它以获得所需的结果,但我觉得只改进我的查询会容易得多。
SELECT stop_times.departure_time, routes.route_long_name, trips.trip_headsign, calendar.monday, calendar.tuesday, calendar.wednesday, calendar.thursday, calendar.friday, calendar.saturday, calendar.sunday
FROM stop_times, trips, routes, calendar
WHERE stop_times.stop_id = '1571' AND stop_times.trip_id = trips.trip_id AND trips.route_id = routes.route_id AND trips.service_id = calendar.service_id AND 20180801 >= calendar.start_date AND 20180801 <= calendar.end_date
ORDER BY routes.route_short_name, trips.service_id, stop_times.departure_time
这是相关的表格。我完全按照 GTFS 文档中指定的方式将数据存储在数据库中。
stops.txt example rows:
routes.txt example rows:
trips.txt 示例行:
stop_times.txt 示例行:
calendar.txt 示例行:
非常感谢您的帮助。
您已经可以做的事情之一是使用标准的 JOIN 表示法。
它更具可读性,并且不太容易导致意外的笛卡尔连接。
并且使用短别名可以使 SQL 更简洁。
SET @StopId = '1571';
SET @CalDate = cast('2018-08-01' as date);
SELECT
st.departure_time,
rte.route_long_name,
tr.trip_headsign,
cal.monday, cal.tuesday, cal.wednesday, cal.thursday, cal.friday,
cal.saturday, cal.sunday
FROM stop_times AS st
JOIN trips AS tr ON tr.trip_id = st.trip_id
JOIN routes AS rte ON rte.route_id = tr.route_id
JOIN calendar AS cal ON cal.service_id = tr.service_id
WHERE st.stop_id = @StopId
AND @CalDate between cal.start_date and cal.end_date
ORDER BY rte.route_short_name, tr.service_id, st.departure_time
至于每条路线获得接下来 2 站的要求?
这里有一个例子 SQL。
它包括工作日的支票。不确定是否需要,所以这只是为了演示。
一个SQLFiddle因为可以找到here
SET @StopId = 1571;
SET @CalDate = cast('2018-08-01' as date);
SET @StartTime = cast('08:00:00' as time);
SELECT departure_time, route_long_name, trip_headsign
FROM
(
SELECT
st.departure_time,
tr.service_id,
rte.route_short_name,
rte.route_long_name,
tr.trip_headsign,
@num := if(@prev_routeid = tr.route_id, @num + 1, 1) as RN,
@prev_routeid := tr.route_id as route_id
FROM stop_times AS st
JOIN trips AS tr ON tr.trip_id = st.trip_id
JOIN routes AS rte ON rte.route_id = tr.route_id
JOIN calendar AS cal ON cal.service_id = tr.service_id
-- LEFT JOIN stops AS s on s.stop_id = st.stop_id
CROSS JOIN (SELECT @num := 0, @type := '') AS vars
WHERE st.stop_id = @StopId
AND @CalDate between cal.start_date and cal.end_date
AND (CASE WEEKDAY(@CalDate)
WHEN 0 THEN monday
WHEN 1 THEN tuesday
WHEN 2 THEN wednesday
WHEN 3 THEN thursday
WHEN 4 THEN friday
WHEN 5 THEN saturday
WHEN 6 THEN sunday
END) = 1
AND st.departure_time >= @StartTime
ORDER BY tr.route_id, st.departure_time
) Q
WHERE RN <= 2
ORDER BY route_short_name, service_id, departure_time;
旁注:
RN 是使用变量以旧的 MySql 7 样式计算的。
在 MySql 8 中,可以使用 window 函数 ROW_NUMBER 代替。