仅含日期(无时间部分)时按记录顺序实现指定范围列求和
解决同日期下按记录ID顺序的金额求和问题
这个需求的核心是要同时结合日期和ID来界定求和范围——因为当多个记录日期相同时,我们需要用ID来区分记录的先后顺序,确保只包含目标ID及更早的记录。
核心思路
我们需要筛选出所有满足以下任一条件的记录:
- 日期早于目标ID对应的日期;
- 日期等于目标ID对应的日期,且ID小于等于目标ID。
然后对这些记录的Amount字段求和即可。
通用SQL实现
假设我们要针对ID=2的记录进行计算,直接用子查询获取目标日期,再构造筛选条件:
SELECT SUM(Amount) AS TotalAmount FROM invoice WHERE -- 早于目标日期的所有记录 Date < (SELECT Date FROM invoice WHERE ID = 2) OR -- 同日期下ID不大于目标ID的记录 (Date = (SELECT Date FROM invoice WHERE ID = 2) AND ID <= 2);
更灵活的变量写法(以MySQL为例)
如果需要动态切换目标ID,可以先把目标ID和对应的日期存为变量,让SQL更易维护:
-- 设置目标ID SET @target_id = 2; -- 获取该ID对应的日期 SET @target_date = (SELECT Date FROM invoice WHERE ID = @target_id); SELECT SUM(Amount) AS TotalAmount FROM invoice WHERE Date < @target_date OR (Date = @target_date AND ID <= @target_id);
验证测试
针对你给出的第一组测试数据:
ID | Amount | Date1 | 50 | 2017-12-08
2 | 100 | 2017-12-11
3 | 150 | 2017-12-11
4 | 250 | 2017-12-12
执行上述SQL后,结果会是50 + 100 = 150,完美排除了同日期下ID=3的记录,符合需求。
可选:窗口函数实现(支持的数据库)
如果你的数据库支持窗口函数(比如PostgreSQL、MySQL 8+、SQL Server等),也可以用累计求和的方式直接获取目标ID的累计值:
SELECT RunningTotal AS TotalAmount FROM ( SELECT ID, SUM(Amount) OVER (ORDER BY Date, ID ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS RunningTotal FROM invoice ) AS sub WHERE ID = 2;
这种方式会计算每条记录的累计求和,最后只取目标ID对应的累计值,结果和之前的方法一致。
内容的提问来源于stack exchange,提问作者Kenjiro
相关产品推荐
相关产品推荐

