PostgreSQL中如何按路线获取最短配送时间对应的数据行
在PostgreSQL中按路线编码筛选最短配送时间的行
这需求挺常见的,我给你整理几种PostgreSQL里的实现方案,你可以根据实际场景选:
先把你的示例表结构和数据用SQL还原出来,方便测试:
CREATE TABLE deliveries ( route_code VARCHAR(10), name VARCHAR(50), time TIME ); INSERT INTO deliveries VALUES ('A', 'McDonald''s', '05:30'), ('A', 'Arby''s', '05:45'), ('A', 'Burger King', '06:00'), ('A', 'Wendy''s', '06:30'), ('B', 'Arby''s', '07:45'), ('B', 'Arby''s', '07:45'), ('B', 'Burger King', '08:00');
方案一:窗口函数(推荐,灵活度高)
窗口函数是PostgreSQL处理这类分组排名需求的利器,这里推荐用RANK()或者ROW_NUMBER(),区别在于如何处理同组内最短时间重复的情况:
用RANK()保留所有最短时间的行
如果同一路线里有多个配送点的时间都是最短的(比如路线B里的两个Arby's),这个方案会把这些行都返回:
SELECT route_code, name, time FROM ( SELECT route_code, name, time, -- 按路线分组,按时间升序排名,最短时间排第1 RANK() OVER (PARTITION BY route_code ORDER BY time ASC) AS rank FROM deliveries ) ranked_deliveries WHERE rank = 1;
用ROW_NUMBER()只返回每组一行
如果不管有没有重复,你只想每组取一行(系统会随机选一个最短时间的行),就用ROW_NUMBER()替换RANK():
SELECT route_code, name, time FROM ( SELECT route_code, name, time, ROW_NUMBER() OVER (PARTITION BY route_code ORDER BY time ASC) AS row_num FROM deliveries ) numbered_deliveries WHERE row_num = 1;
方案二:子查询关联(逻辑直观)
如果你对窗口函数不太熟悉,也可以用子查询先找出每个路线的最短时间,再关联原表获取完整行数据,同样会保留所有最短时间的行:
SELECT d.route_code, d.name, d.time FROM deliveries d INNER JOIN ( -- 先按路线分组,计算每组的最短时间 SELECT route_code, MIN(time) AS min_time FROM deliveries GROUP BY route_code ) route_min_times ON d.route_code = route_min_times.route_code AND d.time = route_min_times.min_time;
注意事项
如果你的TIME字段是字符串类型(比如示例里的...),一定要先转换成TIME类型再排序,否则会出现排序错误。转换方式可以用:
CAST(time AS TIME) -- 或者PostgreSQL特有的简写 time::TIME
比如修改窗口函数里的排序部分:
ORDER BY CAST(time AS TIME) ASC
内容的提问来源于stack exchange,提问作者Emac
相关产品推荐
相关产品推荐

