MySQL如何按加油站和燃油类型分组查询最新价格记录
解决每个加油站每种燃油类型的最新价格查询问题
原SQL的问题分析
你的查询无法得到预期结果,核心问题有三点:
- 子查询仅按
station_id分组,没有考虑type_of_fuel,无法区分同一加油站下不同燃油类型的最新记录 - 分组时包含唯一主键
id,导致每个分组仅对应单条记录,MAX(updated_timestamp)失去统计意义 - 关联条件
T.id = SUB.id逻辑错误,子查询的id并非对应各分组最新时间的记录ID
正确SQL语句及原理
方法一:分组子查询关联(兼容旧版本数据库)
SELECT t.* FROM fuel_prices t INNER JOIN ( SELECT station_id, type_of_fuel, MAX(updated_timestamp) AS latest_timestamp FROM fuel_prices GROUP BY station_id, type_of_fuel ) sub ON t.station_id = sub.station_id AND t.type_of_fuel = sub.type_of_fuel AND t.updated_timestamp = sub.latest_timestamp;
原理:
- 子查询按
station_id和type_of_fuel组合分组,计算每组的最新更新时间latest_timestamp - 将原表与子查询结果关联,匹配每个加油站-燃油类型组合中时间等于最新时间的记录,得到该组合的最新价格数据
方法二:窗口函数法(高效简洁,支持窗口函数的数据库适用)
如果你的数据库支持窗口函数(如MySQL 8.0+、PostgreSQL、SQL Server等),推荐使用这种方法:
SELECT id, station_id, updated_timestamp, price, type_of_fuel FROM ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY station_id, type_of_fuel ORDER BY updated_timestamp DESC ) AS rn FROM fuel_prices ) t WHERE rn = 1;
原理:
- 使用
PARTITION BY station_id, type_of_fuel将数据按「加油站+燃油类型」分组 - 每组内按
updated_timestamp降序排序,用ROW_NUMBER()为每条记录分配序号,最新的记录序号为1 - 外层查询筛选出序号为1的记录,即为每个组合的最新价格记录
两种方法对比
- 方法一兼容性更好,适用于不支持窗口函数的旧版本数据库
- 方法二逻辑更直观,避免了多表关联,在数据量较大时性能更优
内容的提问来源于stack exchange,提问作者simonelippolis
相关产品推荐
相关产品推荐

