MySQL按业务规则计算月度滞纳金 筛选符合条件的StatementItem条目
问题背景
现有StatementItem表存储企业账单明细:
- 滞纳金、已享受服务费用对应
si_amount为负值,其中sid=29的条目为滞纳金记录 - 已缴纳服务款项对应
si_amount为正值
需要按规则计算指定月份客户滞纳金,通用公式为:late_fee = (出账满1个月且未被计收满3次滞纳金的服务总费用 + 累计已缴总金额) * 1.5%
核心规则约束: - 服务项生成时间早于3条同客户滞纳金记录的,视为已累计计收3次滞纳金,不得计入当月计算基数
- 仅出账时间早于当期账期截止日(如示例为2022-05-20)的服务项可纳入计算
实现方案
原查询存在三个问题:表别名引用错误、未过滤滞纳金条目本身、未实现「计收次数不足3次」的判断逻辑,修正后完整SQL如下:
SELECT c.c_id, -- 符合条件的服务总费用 COALESCE( ( SELECT SUM(si.si_amount) FROM StatementItem si WHERE si.c_id = c.c_id AND si.si_amount < 0 AND si.sid != 29 -- 排除滞纳金自身的负金额记录 AND si.si_posting_date < '2022-05-20' -- 替换为对应计算月份的账期截止日 -- 统计该服务项之后生成的滞纳金记录数,不足3条才符合条件 AND ( SELECT COUNT(1) FROM StatementItem late_count WHERE late_count.c_id = si.c_id AND late_count.sid = 29 AND late_count.si_posting_date > si.si_posting_date ) < 3 ), 0 ) AS total_eligible_for_late_fees, -- 累计已缴总金额 COALESCE( ( SELECT SUM(si_amount) FROM StatementItem si WHERE si.c_id = c.c_id AND si.si_amount > 0 ), 0 ) AS all_payments_to_date, -- 计算最终滞纳金 (total_eligible_for_late_fees + all_payments_to_date) * 0.015 AS late_fee FROM Customer c;
优化说明
- 用
COALESCE处理SUM返回的NULL值,避免无符合条件记录时计算结果为空 - 若表数据量较大,建议给
StatementItem表添加(c_id, sid, si_posting_date)的联合索引,大幅提升子查询计数、求和的执行效率 - 可将硬编码的账期日期
'2022-05-20'替换为变量,适配不同月份的滞纳金计算需求
内容的提问来源于stack exchange,提问作者J.spenc
相关产品推荐
相关产品推荐

