SQL分组查询如何获取按时间倒序的最新Price记录
这个需求两种实现方式都支持,不是必须用子查询,部分数据库可直接通过聚合函数完成,以下是不同场景的实现方案:
方案1:无需子查询,用聚合函数直接实现(适配支持高级聚合特性的数据库)
如果你的数据库支持ARRAY_AGG(PostgreSQL、BigQuery等)或者GROUP_CONCAT(MySQL、SQLite等)类聚合函数,可以直接在分组时对Timestamp倒序排序,取排序后的第一个Price即可:
- PostgreSQL 写法示例:
SELECT t1.Supplier, t2.Product, (ARRAY_AGG(t1.Price ORDER BY t1.Timestamp DESC))[1] AS latest_price FROM t1 INNER JOIN t2 ON t1.ProductCode = t2.ProductCode GROUP BY t1.Supplier, t2.Product
- MySQL 8.0+ 写法示例:
SELECT t1.Supplier, t2.Product, SUBSTRING_INDEX(GROUP_CONCAT(t1.Price ORDER BY t1.Timestamp DESC), ',', 1) AS latest_price FROM t1 INNER JOIN t2 ON t1.ProductCode = t2.ProductCode GROUP BY t1.Supplier, t2.Product
注意MySQL方案受GROUP_CONCAT默认长度限制,仅适合Price字段值不包含逗号的场景,数据量较大时建议优先用窗口函数方案
方案2:窗口函数实现(可读性高,兼容所有支持SQL标准窗口函数的数据库)
用ROW_NUMBER窗口函数对分组内数据按时间倒序打行号标记,过滤行号为1的记录即可,兼容MySQL 8.0+、PostgreSQL、SQL Server、Oracle等所有主流新版本数据库:
WITH ranked_data AS ( SELECT t1.Supplier, t2.Product, t1.Price, ROW_NUMBER() OVER (PARTITION BY t1.Supplier, t2.Product ORDER BY t1.Timestamp DESC) AS rn FROM t1 INNER JOIN t2 ON t1.ProductCode = t2.ProductCode ) SELECT Supplier, Product, Price AS latest_price FROM ranked_data WHERE rn = 1
方案3:子查询实现(兼容所有数据库版本,包括不支持新特性的老版本)
如果是不支持上述特性的老版本数据库,可以通过子查询先获取每个分组的最大时间戳,再关联回原表取对应的Price值:
SELECT t1.Supplier, t2.Product, t1.Price AS latest_price FROM t1 INNER JOIN t2 ON t1.ProductCode = t2.ProductCode INNER JOIN ( SELECT Supplier, MAX(Timestamp) AS max_ts FROM t1 GROUP BY Supplier ) latest_ts ON t1.Supplier = latest_ts.Supplier AND t1.Timestamp = latest_ts.max_ts GROUP BY t1.Supplier, t2.Product, t1.Price
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

