如何将含日期间隔的税额表按单日聚合,解决大数据量递归低效问题
高性能税额按日聚合实现方案
采用时间线差分法替代递归CTE的行展开逻辑,可避免行数爆炸,适配千万级数据量场景。
核心思路
- 无需展开每个时间段的全部日期,仅对每个税额区间的起止点做增减标记:
- 区间起始日
date_from:加对应tax值 - 区间结束日的次日
DATE_ADD(date_to, INTERVAL 1 DAY):减对应tax值
- 区间起始日
- 按人员、日期排序后做滚动累计求和,得到的累计值就是对应日期的总税额
- 若需要输出完整连续的日期区间,可提前预生成一张日历维度表关联补全
实现代码(兼容SQL Server/MySQL 8.0+/PostgreSQL)
WITH tax_diff AS ( -- 生成差分事件:起始加税,结束次日减税 SELECT person, date_from AS event_date, tax AS delta FROM my_table WHERE date_from >= @date_from AND date_to < @date_to UNION ALL SELECT person, DATEADD(DAY, 1, date_to) AS event_date, -tax AS delta FROM my_table WHERE date_from >= @date_from AND date_to < @date_to ), -- 先按人员、日期聚合差分,减少后续计算行数 agg_diff AS ( SELECT person, event_date, SUM(delta) AS delta FROM tax_diff GROUP BY person, event_date ), running_total AS ( -- 按人员、日期排序后滚动求和 SELECT person, event_date, SUM(delta) OVER (PARTITION BY person ORDER BY event_date) AS daily_tax FROM agg_diff ) -- 如需补全连续日期,可在此处LEFT JOIN预生成的日历表,空tax值填充0即可 SELECT event_date AS `date`, person, daily_tax AS tax FROM running_total -- 过滤查询时间范围外的日期 WHERE event_date BETWEEN @date_from AND @date_to ORDER BY person, event_date;
性能说明
递归CTE的时间复杂度和总日期跨度正相关:如果单条记录平均覆盖30天,500万条记录会展开为1.5亿行,计算、内存开销极高。
差分法仅需处理2倍原数据量的行(500万条记录仅生成1000万行差分事件),仅需要一次排序加窗口聚合操作,性能提升10~100倍不等,完全适配500万级数据量场景。
内容的提问来源于stack exchange,提问作者qtsar
相关产品推荐
相关产品推荐

