构建基于历史列车站点时间数据的后续结果查询语句
针对你给出的列车158的「列车-站点-时间」数据,当前处于Station3,想要查询后续的相关记录,我整理了几种实用的SQL实现方式,适配不同的场景需求:
场景1:基于时间顺序获取所有后续记录
如果你的数据时间是严格按站点先后顺序记录的,最简单的方式是先找到Station3的最后一条记录时间,再筛选同一列车中晚于该时间的所有条目:
SELECT * FROM train_schedule WHERE train_id = '158' AND record_time > ( SELECT MAX(record_time) FROM train_schedule WHERE train_id = '158' AND station = 'Station3' ) ORDER BY record_time ASC;
这个语句会返回列车158中,所有时间晚于Station3最后一条记录(11:45)的条目,也就是Station4的全部11:50-11:53的记录。
场景2:基于固定站点顺序查询(不受时间数据影响)
如果你的站点有固定的行驶顺序(比如Station1→Station2→Station3→Station4),即使时间数据偶尔有异常,也可以通过自定义站点顺序来查询:
WITH station_order AS ( SELECT 'Station1' AS station, 1 AS order_num UNION ALL SELECT 'Station2' AS station, 2 AS order_num UNION ALL SELECT 'Station3' AS station, 3 AS order_num UNION ALL SELECT 'Station4' AS station, 4 AS order_num ) SELECT ts.* FROM train_schedule ts JOIN station_order so ON ts.station = so.station WHERE ts.train_id = '158' AND so.order_num > ( SELECT order_num FROM station_order WHERE station = 'Station3' ) ORDER BY so.order_num, ts.record_time ASC;
这个方法通过CTE定义站点的行驶顺序,直接筛选出Station3之后的所有站点记录,适合依赖固定站点逻辑的场景。
场景3:仅获取紧邻的下一个站点记录
如果你只需要Station3之后的第一个站点(也就是Station4)的记录,可以用窗口函数给站点排序后查询:
WITH ranked_stations AS ( SELECT DISTINCT train_id, station, ROW_NUMBER() OVER (PARTITION BY train_id ORDER BY MIN(record_time) ASC) AS station_rank FROM train_schedule GROUP BY train_id, station ) SELECT ts.* FROM train_schedule ts JOIN ranked_stations rs ON ts.train_id = rs.train_id AND ts.station = rs.station WHERE rs.train_id = '158' AND rs.station_rank = ( SELECT station_rank + 1 FROM ranked_stations WHERE train_id = '158' AND station = 'Station3' ) ORDER BY ts.record_time ASC;
这个语句先按每个站点的最早记录时间给列车的站点排序,再找到Station3的下一个排名对应的站点,返回该站点的所有记录。
小提示
如果你的record_time是字符串类型,要确保它能正确排序(比如'11:45'这种HH:MI格式是可以直接按字符串排序的)。如果是其他格式,需要转换为时间类型,比如MySQL用STR_TO_DATE(record_time, '%H:%i'),PostgreSQL用TO_TIMESTAMP(record_time, 'HH24:MI')替换语句中的record_time即可。
内容的提问来源于stack exchange,提问作者Simon

