如何仅获取ROW_NUMBER中rn=1的行 无需计算全量rn提升查询速度
优化方案
方案1:使用LATERAL JOIN(支持MySQL 8.0.14+、PostgreSQL等主流数据库,性能最优)
你的需求本质是取每个(storeID, skuID)分组下effectiveDate最新的1条记录,LATERAL JOIN可以直接让数据库每个分组只扫描1条符合要求的记录,不需要计算全部分组的行号:
SELECT itm.* FROM ( -- 先取所有需要查询的分组,可在此处添加你的按月过滤等前置条件 SELECT DISTINCT storeID, skuID FROM itm WHERE [你的时间范围过滤条件] ) AS grp JOIN LATERAL ( SELECT * FROM itm WHERE itm.storeID = grp.storeID AND itm.skuID = grp.skuID AND [你的其余过滤条件,和原查询保持一致] ORDER BY effectiveDate DESC LIMIT 1 ) AS itm ON TRUE
注意:需要提前给
itm表建立(storeID, skuID, effectiveDate DESC)的联合索引,索引建对的情况下,扫描行数仅为你最终需要的rn=1的行数,比原窗口函数写法少扫描90%以上的数据。
方案2:使用MAX()关联查询(兼容所有数据库版本,无需LATERAL支持)
如果你的数据库版本不支持LATERAL JOIN,可以用分组取最大日期再关联的写法,性能同样远高于原窗口函数方案:
SELECT t1.* FROM itm t1 INNER JOIN ( SELECT storeID, skuID, MAX(effectiveDate) AS max_effective_date FROM itm WHERE [你的时间范围、其余过滤条件] GROUP BY storeID, skuID ) t2 ON t1.storeID = t2.storeID AND t1.skuID = t2.skuID AND t1.effectiveDate = t2.max_effective_date
如果存在同个分组下多条记录
effectiveDate完全相同的场景,可以额外加去重逻辑处理即可。
Laravel适配说明
上述两种方案都是标准SQL写法,不需要使用临时表,完全兼容Laravel的读写分离架构,直接用查询构造器组装对应SQL即可正常执行。
内容的提问来源于stack exchange,提问作者jove0610
相关产品推荐
相关产品推荐

