积分流水与余额勾稽
积分用流水事实记录每一次变动:获取、消耗、过期、调整,一次变动一行。余额可以由流水累计推导,也可以定期物化成余额快照来加速查询。两类数据必须能相互勾稽:末态余额应当等于流水净额,对不上就说明有漏记、重复记录或人工直接改数。
基本信息
| 事件类型 | 获取 / 消耗 / 过期 / 调整 |
|---|---|
| 余额表达 | 快照物化或由流水累计推导 |
| 勾稽关系 | 末态余额 = 流水净额 |
| 过期处理 | 用事件表达负向变动,不删历史获取记录 |
| 调整单 | 必须带原因码与操作人 |
| 有效期 | 积分常按批次到期,需按批次管理 |
典型使用场景
- 会员权益:查询可用积分余额,支撑兑换与抵扣
- 成本核算:按获取与消耗节奏测算积分的实际兑付成本
- 过期回收:按批次到期规则计算应回收积分并生成过期事件
- 风控核查:识别单日大量获取或集中消耗的异常账户
- 对账核验:流水净额与余额快照逐用户比对,定位差异来源
余额推导与勾稽校验
余额推导与勾稽校验
SELECT user_id,
sum(CASE WHEN type = 'earn' THEN pts ELSE -pts END) AS balance -- 获取为正,其余为负
FROM fact_points_ledger
GROUP BY user_id;
SELECT l.user_id, l.balance AS ledger_balance, s.balance AS snap_balance,
l.balance - s.balance AS diff -- 非零即存在差异,需逐用户排查
FROM (SELECT user_id, sum(CASE WHEN type = 'earn' THEN pts ELSE -pts END) AS balance
FROM fact_points_ledger GROUP BY user_id) l
JOIN fact_points_snapshot s ON l.user_id = s.user_id
WHERE l.balance <> s.balance;积分数据两类形态
| 形态 | 优点 | 注意点 |
|---|---|---|
| 流水事实 | 可追溯每次变动,可重算 | 用户量增长后累计计算成本高 |
| 余额快照 | 查询快,支持实时展示 | 必须与流水勾稽,否则账实不符 |
| 批次信息 | 支撑按批次过期 | 批次与消耗的匹配规则要固定 |
积分过期用事件表达(负向变动),不要直接改历史获取记录:改了获取记录,历史发放报表与用户感知都会变化,且失去了对账依据。
消耗积分时用哪个批次的积分(先进先出还是先到期先出)会直接影响过期数量,这不是技术细节而是业务规则,必须在模型文档里写明并在实现中统一。