-
-
Save stebazzi/7f9d68f04df6ff91a49e8e6c646abed1 to your computer and use it in GitHub Desktop.
MySQL Stored Procedure to get upcoming bus times for a stop from GTFS data. This query includes buses that started running before midnight on the night before but continue through the current day. It also includes service additions and removals from calendar_dates. WARNING: without the proper indices, this query can be VERY slow. See my other Gi…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
DELIMITER $$ | |
DROP PROCEDURE IF EXISTS `ocdata`.`getNextTripsForStop`$$ | |
CREATE PROCEDURE `ocdata`.`getNextTripsForStop` ( | |
IN SelectedStop VARCHAR(6), | |
IN SearchDateTime DATETIME | |
) | |
BEGIN | |
SET @StopID = SelectedStop; | |
SET @DateToday = SearchDateTime; | |
SET @DateYesterday = DATE_SUB(@DateToday, INTERVAL 1 DAY); | |
SET @DateTomorrow = DATE_ADD(@DateToday, INTERVAL 1 DAY); | |
SET @monday = IF(LCASE(DATE_FORMAT(@DateToday,'%W')) = 'monday', 1, NULL); | |
SET @tuesday = IF(LCASE(DATE_FORMAT(@DateToday,'%W')) = 'tuesday', 1, NULL); | |
SET @wednesday = IF(LCASE(DATE_FORMAT(@DateToday,'%W')) = 'wednesday', 1, NULL); | |
SET @thursday = IF(LCASE(DATE_FORMAT(@DateToday,'%W')) = 'thursday', 1, NULL); | |
SET @friday = IF(LCASE(DATE_FORMAT(@DateToday,'%W')) = 'friday', 1, NULL); | |
SET @saturday = IF(LCASE(DATE_FORMAT(@DateToday,'%W')) = 'saturday', 1, NULL); | |
SET @sunday = IF(LCASE(DATE_FORMAT(@DateToday,'%W')) = 'sunday', 1, NULL); | |
SET @ymonday = IF(LCASE(DATE_FORMAT(@DateYesterday,'%W')) = 'monday', 1, NULL); | |
SET @ytuesday = IF(LCASE(DATE_FORMAT(@DateYesterday,'%W')) = 'tuesday', 1, NULL); | |
SET @ywednesday = IF(LCASE(DATE_FORMAT(@DateYesterday,'%W')) = 'wednesday', 1, NULL); | |
SET @ythursday = IF(LCASE(DATE_FORMAT(@DateYesterday,'%W')) = 'thursday', 1, NULL); | |
SET @yfriday = IF(LCASE(DATE_FORMAT(@DateYesterday,'%W')) = 'friday', 1, NULL); | |
SET @ysaturday = IF(LCASE(DATE_FORMAT(@DateYesterday,'%W')) = 'saturday', 1, NULL); | |
SET @ysunday = IF(LCASE(DATE_FORMAT(@DateYesterday,'%W')) = 'sunday', 1, NULL); | |
SELECT stop_name, | |
route_short_name, | |
trip_headsign, | |
IF(arrival_time >= '24:00:00', SUBTIME(arrival_time,'24:00:00'),arrival_time) AS ArrivalTime, | |
ArrivalDate, | |
CONCAT(ArrivalDate, ' ', IF(arrival_time >= '24:00:00', SUBTIME(arrival_time,'24:00:00'),arrival_time)) AS ArrivalDateTime | |
FROM ( | |
SELECT s.stop_name, | |
r.route_short_name, | |
t.trip_headsign, | |
st.arrival_time, | |
DATE(IF(st.arrival_time >= '24:00:00', DATE_ADD(@DateYesterday, INTERVAL 1 DAY), @DateYesterday)) AS ArrivalDate | |
FROM stops s | |
INNER JOIN stop_times st ON s.stop_id = st.stop_id | |
INNER JOIN trips t ON st.trip_id = t.trip_id | |
INNER JOIN routes r ON t.route_id = r.route_id | |
INNER JOIN calendar c ON t.service_id = c.service_id | |
WHERE c.service_id IN ( | |
SELECT service_id | |
FROM calendar c | |
WHERE DATE_FORMAT(@DateYesterday, '%Y%m%d') BETWEEN c.start_date AND c.end_date | |
AND ( | |
c.monday = @ymonday | |
OR c.tuesday = @ytuesday | |
OR c.wednesday = @ywednesday | |
OR c.thursday = @ythursday | |
OR c.friday = @yfriday | |
OR c.saturday = @ysaturday | |
OR c.sunday = @ysunday | |
) | |
AND service_id NOT IN ( | |
SELECT service_id FROM calendar_dates WHERE date = @DateYesterday AND exception_type = 2 | |
) | |
UNION | |
SELECT c.service_id | |
FROM calendar c | |
INNER JOIN calendar_dates cd ON c.service_id = cd.service_id | |
WHERE cd.exception_type = 1 | |
AND cd.date = @DateYesterday | |
) | |
AND s.stop_code = @StopID | |
HAVING CONCAT(ArrivalDate, ' ', arrival_time) > @DateToday | |
UNION | |
SELECT s.stop_name, | |
r.route_short_name, | |
t.trip_headsign, | |
st.arrival_time, | |
DATE(IF(st.arrival_time >= '24:00:00', DATE_ADD(@DateToday, INTERVAL 1 DAY), @DateToday)) AS ArrivalDate | |
FROM stops s | |
INNER JOIN stop_times st ON s.stop_id = st.stop_id | |
INNER JOIN trips t ON st.trip_id = t.trip_id | |
INNER JOIN routes r ON t.route_id = r.route_id | |
INNER JOIN calendar c ON t.service_id = c.service_id | |
WHERE c.service_id IN ( | |
SELECT service_id | |
FROM calendar c | |
WHERE DATE_FORMAT(@DateToday, '%Y%m%d') BETWEEN c.start_date AND c.end_date | |
AND ( | |
c.monday = @monday | |
OR c.tuesday = @tuesday | |
OR c.wednesday = @wednesday | |
OR c.thursday = @thursday | |
OR c.friday = @friday | |
OR c.saturday = @saturday | |
OR c.sunday = @sunday | |
) | |
AND service_id NOT IN ( | |
SELECT service_id FROM calendar_dates WHERE date = @DateToday AND exception_type = 2 | |
) | |
UNION | |
SELECT c.service_id | |
FROM calendar c | |
INNER JOIN calendar_dates cd ON c.service_id = cd.service_id | |
WHERE cd.exception_type = 1 | |
AND cd.date = @DateToday | |
) | |
AND s.stop_code = @StopID | |
HAVING CONCAT(ArrivalDate, ' ', arrival_time) > @DateToday | |
) a | |
HAVING ArrivalDateTime BETWEEN @DateToday AND DATE_ADD(@DateToday, INTERVAL 1 HOUR) | |
ORDER BY ArrivalDateTime; | |
END; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment