如何基于两列拼接的标识符筛选每组最大日期对应的SQL行数据
问题原因
- 你现有查询的核心错误是
GROUP BY子句包含了Quantity字段:Identifier由ItemNo+Lot拼接而成,是你要分组的唯一维度,但如果同一个Identifier下存在不同的Quantity值,SQL会把它们拆分为多个独立分组,每个分组单独计算最大过账日期,最终就会出现同一个Identifier返回多行的非预期结果。 - 另外原查询还存在两处语法错误:
Groupy是拼写错误,应为GROUP BY;拼接Identifier的表达式少了加号,正确写法是L.ItemNo+' '+L.Lot。
正确实现方案
通用方案(兼容主流新版数据库)
最简洁的实现方式是使用窗口函数ROW_NUMBER(),按Identifier分区、按PostingDate倒序排序,取每个分区排名第一的行即可,兼容SQL Server、PostgreSQL、MySQL 8.0+、Oracle等绝大多数主流数据库:
WITH RankedLines AS ( SELECT L.ItemNo + ' ' + L.Lot AS Identifier, L.PostingDate, L.ItemNo, L.Description, L.Quantity, L.Lot, -- 按Identifier分组,过账日期倒序排名,最新的日期排第一 ROW_NUMBER() OVER (PARTITION BY L.ItemNo, L.Lot ORDER BY L.PostingDate DESC) AS rn FROM dbo.JournalLine L ) SELECT Identifier, PostingDate, ItemNo, Description, Quantity, Lot FROM RankedLines WHERE rn = 1;
老版本数据库兼容方案(如MySQL 5.x)
如果你的数据库不支持CTE和窗口函数,可以用关联子查询实现:
SELECT L.ItemNo + ' ' + L.Lot AS Identifier, L.PostingDate, L.ItemNo, L.Description, L.Quantity, L.Lot FROM dbo.JournalLine L INNER JOIN ( SELECT ItemNo, Lot, MAX(PostingDate) AS MaxPostingDate FROM dbo.JournalLine GROUP BY ItemNo, Lot ) T ON L.ItemNo = T.ItemNo AND L.Lot = T.Lot AND L.PostingDate = T.MaxPostingDate
特殊场景说明
如果同一个Identifier存在多条相同最大PostingDate的记录,你希望全部保留的话,把通用方案里的ROW_NUMBER()替换为RANK()即可。
内容的提问来源于stack exchange,提问作者Brendan Lesinski
相关产品推荐
相关产品推荐

