如何在聚合查询中包含最早过账交易的原始金额?
如何在冲销交易聚合查询中添加每组最早过账日期的原始金额?
你当前的查询已经能精准筛选出金额总和为0的冲销交易组了,现在想要给结果加上每组里过账日期(PostedDate)最早的那笔交易的原始金额,对吧?结合你给出的示例数据和预期结果,我给你两种可行的解决方案:
方案一:用ROW_NUMBER()标记最早记录
这种方法兼容性较强,几乎所有支持窗口函数的数据库都能使用:
WITH RankedTransactions AS ( SELECT [Account], [Voucher], [DocumentDate], [Amount], -- 按分组字段划分组,每组内按PostedDate升序排号,最早的记录标记为1 ROW_NUMBER() OVER (PARTITION BY [Account], [Voucher], [DocumentDate] ORDER BY [PostedDate] ASC) AS rn FROM MyTable WHERE [Account] = 'abc' ) SELECT rt.[Account], rt.[Voucher], rt.[DocumentDate], -- 提取每组中标记为1的记录的金额作为原始金额 MAX(CASE WHEN rn = 1 THEN rt.[Amount] END) AS OriginalAmount, SUM(rt.[Amount]) AS [Sum(Amount)], COUNT(*) AS Records FROM RankedTransactions rt GROUP BY rt.[Account], rt.[Voucher], rt.[DocumentDate] HAVING SUM(rt.[Amount]) = 0;
逻辑说明:
- 先用CTE
RankedTransactions给每条记录按Account、Voucher、DocumentDate分组,组内按PostedDate从小到大排序,最早的记录会被标记为rn=1; - 后续聚合查询中,通过
MAX(CASE WHEN rn=1 THEN Amount END)提取每组最早交易的金额(因为每组只有一条rn=1的记录,用MIN也能达到同样效果); - 保留你原有的
SUM(Amount)计算,新增COUNT(*)统计每组的记录数,最后用HAVING过滤出总和为0的冲销组。
用你的示例数据测试的话,会完美输出预期结果:OriginalAmount=100.00,Sum(Amount)=0.00,Records=2。
方案二:用FIRST_VALUE()直接获取最早金额
如果你的数据库支持FIRST_VALUE函数(比如SQL Server 2012+、PostgreSQL、MySQL 8.0+等),这种写法会更直观:
WITH GroupedWithFirstAmount AS ( SELECT [Account], [Voucher], [DocumentDate], [Amount], -- 直接获取每组内PostedDate最早的交易金额 FIRST_VALUE([Amount]) OVER (PARTITION BY [Account], [Voucher], [DocumentDate] ORDER BY [PostedDate] ASC) AS OriginalAmount FROM MyTable WHERE [Account] = 'abc' ) SELECT DISTINCT [Account], [Voucher], [DocumentDate], OriginalAmount, SUM([Amount]) OVER (PARTITION BY [Account], [Voucher], [DocumentDate]) AS [Sum(Amount)], COUNT(*) OVER (PARTITION BY [Account], [Voucher], [DocumentDate]) AS Records FROM GroupedWithFirstAmount WHERE SUM([Amount]) OVER (PARTITION BY [Account], [Voucher], [DocumentDate]) = 0;
逻辑说明:
- 用
FIRST_VALUE窗口函数直接在CTE中获取每组最早过账交易的金额; - 之后用窗口聚合函数
SUM()和COUNT()计算每组的总金额和记录数,最后通过DISTINCT去重并过滤出总和为0的组。
两种方案都能满足你的需求,你可以根据自己使用的数据库类型和个人习惯选择。
内容的提问来源于stack exchange,提问作者Steve
相关产品推荐
相关产品推荐

