订阅更新

优惠券数仓怎么建模?发券、领券、用券能只看一张状态表吗?

面试问 335 约 3 分钟读完

本文目录
  1. 面试怎么回答
  2. 先问业务,一张“券”究竟指什么
  3. 当前状态解决查询,事件流水解决解释
  4. 转化率需要一批固定的券和同一个观察窗口
  5. 面额不是实际优惠,更不等于商家成本
  6. 一个典型场景:昨天的核销人数今天变少了
  7. 验收不止看一条状态能否流转

面试怎么回答

我会把券模板、用户券实例和核销流水分开建模。模板描述规则,实例记录归属和生命周期,事件保留领取、核销、撤销及时间。转化率用同批次实例和固定观察窗口计算,不能用当天核销除当天发放。金额还要区分券面额、实际抵扣和承担成本;退款后是否退券按业务规则保留反向事件,不能只覆盖当前状态。

先把这段讲顺;面试官追问时,再展开下面的原理和细节。

详细讲解

运营问:“昨天发出去的券,今天用了多少?”开发打开优惠券表,按当前状态等于已使用计数。数字能出来,但“昨天发出去的那批券”和“今天发生的用券”,还没有真正关联起来。

优惠券模板、用户券实例和核销事件属于不同粒度;保留生命周期流水,才能解释转化、撤销和历史时点状态。

先问业务,一张“券”究竟指什么

模板是一个活动的规则定义,例如满足门槛后减免一定金额。用户券实例是具体发给某个用户的一份权益,应有能够稳定识别的实例ID。

核销则是一次业务事件,关联某个券实例与订单。发放、领取、锁定、使用、解锁、撤销、过期是否都存在,取决于产品流程,不应强行套用统一状态机。

有些业务发放即到账,不存在额外领取动作;有些券码由用户激活后才归属。设计前先画清真实流程,再决定哪些事件与字段有必要保留。

同一张券,三种粒度不能混在一起数

当前状态解决查询,事件流水解决解释

券实例当前状态表适合查现在是否可用。它不能独立回答昨天处于什么状态、什么时候首次使用、退款后是否恢复过可用。

生命周期事件表记录事件ID、实例ID、事件类型、业务发生时间、来源版本和关联订单。事件重试按事件身份幂等,不应按“同一张券”去重,否则会丢掉不同合法动作。

当前状态可以由可信业务状态或事件顺序维护,但事件时间相同、晚到及乱序时,要有可比较的来源次序。收到较晚到达的旧事件,不能无条件覆盖新状态。

转化率需要一批固定的券和同一个观察窗口

“九月一日发出的券,七天内核销率”应先固定发放批次或实例集合,再观察这些实例在规定窗口内是否发生有效核销。

九月二日核销的券,可能是一周前发出的。拿当天核销数除以当天发券数,得到的不是同一批券的转化率,甚至可能超过百分之百。

还要明确分母是成功发放、成功到账,还是用户主动领取的实例;分子是至少成功用过一次,还是截至观察时点仍未撤销的核销。名称相近的指标,可以有不同含义,但不能共用一个模糊字段。

观察窗口尚未结束的批次应标注未成熟。比较七天核销率时,不能把刚发一天的批次直接与完整观察七天的批次排名。

面额不是实际优惠,更不等于商家成本

一张面额二十元的券,可能受订单金额、封顶或叠加规则影响,实际只抵扣部分金额。平台和商家如何分担,通常又是另一组金额。

建议在核销粒度保存实际抵扣与承担方金额,必要时关联到订单明细分摊结果。不要把面额乘核销张数当成所有场景的优惠成本。

多张券叠加一笔订单时,订单金额会在核销明细中重复出现。应先按指标目标聚合,或者关联订单粒度结果,不能直接把关联后的订单金额求和。

一个典型场景:昨天的核销人数今天变少了

假设昨天报告有一批已使用优惠券,今天查询同一天却减少。第一反应是历史分区丢失,但任务与行数都正常。

原因是订单退款后券实例被改回可用,报表按当前状态反推历史。旧校验只验证实例表主键唯一,没有检查状态覆盖是否破坏历史解释。

修正保留核销及撤销事件,区分“当日发生的核销”和“截至某时点净有效核销”,同时规定退款后券是否恢复、是否延长有效期。若原始历史事件缺失,应说明可还原范围,不能编造过去的动作。

验收不止看一条状态能否流转

测试至少覆盖重复事件、用券失败后解锁、成功核销后撤销、过期与退款交叉、同一订单多券等路径,并逐条核对实例数量和金额守恒关系。

这些校验不是要把数仓变成发券系统。数仓负责忠实记录并解释业务事实,真正的券可用性与交易扣减仍由业务系统负责。模型不能因为分析方便就替业务创造新的状态规则。

刷题进度保存在当前浏览器