订阅更新

订单拆单、合单后怎么建模?父子订单的金额和单量怎么统计?

面试问 285 约 3 分钟读完

本文目录
  1. 面试怎么回答
  2. 先把三个业务对象分开
  3. 关系应尽量落到能解释分配的层次
  4. 哪一层拥有金额,哪一层拥有单量?
  5. 一个典型场景:去重订单号救不了双重计量
  6. 重新拆分与退款,才是模型的压力测试

面试怎么回答

我会把交易、履约和支付拆成不同粒度的事实表,分别定义订单数、发货单数和支付次数。拆单或合单通过明细映射追踪,金额分配保留规则和版本,不把父子订单简单并集后求和。取消、退款和重新拆分需要关联原业务对象并防止旧版本重复生效。验收同时检查金额守恒、商品数量和关系覆盖,不能只验证订单号唯一。

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

详细讲解

用户只下了一次单,仓库却发了三个包裹,支付系统又只有一笔扣款。面试官继续问:“你说昨天有多少订单,到底是在数哪一种?”如果交易订单、履约子单、支付单都叫 order_id,后面的去重和对账很快就会失去依据。

交易、履约和支付不是同一种订单粒度;拆合关系用于追踪,金额与单量必须在各自事实粒度统计。

先把三个业务对象分开

交易订单表达一次购买约定,通常关心成交额、购买人数和交易单量。履约单表达仓库或商家执行的发货任务,关心发货时效、包裹和履约次数。

支付单表达一次资金动作,可能一笔支付覆盖多笔交易,也可能一笔交易经历多次支付尝试。未成功的支付尝试不能直接算成交。

这三类对象有关联,但并不存在永远稳定的一对一关系。把它们强行压成一个订单主表,再用一个 order_id 解释所有指标,会让最初简单的设计在拆合发生后崩掉。

关系应尽量落到能解释分配的层次

一笔父交易包含多个商品行,按仓库拆成不同履约子单。只保存父子单号,有时能追踪关系,却不足以解释哪件商品去了哪个子单。

更完整的关系可以包含交易明细键、履约明细键、数量和分配金额,必要时保留关系生效版本。合单发货时,多个交易明细可能共同进入同一履约对象。

关联表的作用是追踪,不代表可以沿它任意连接两个事实后求和。一条交易明细分两次发货,就可能在履约侧出现两行;直接带入交易总金额仍会重复。

一次购买,可以对应不同的业务计数

哪一层拥有金额,哪一层拥有单量?

交易成交额应从符合状态口径的交易事实汇总,履约单量从有效履约事实计数,成功支付金额从资金事实核对。

需要分析仓库成交额时,才将交易金额依据商品、数量或约定规则分配到履约粒度。运费、优惠和税费可能采用不同分摊方式,不能默认每个子单平分。

例如100元交易拆成60元和40元的两部分,两部分上卷仍是100元。父交易的100元与子单的60、40同时 SUM,得到200元,虽然每个单号都唯一,金额仍然被算了两次。

一个典型场景:去重订单号救不了双重计量

比如报表把父订单和子订单统一 UNION ALL,认为不同单号代表不同有效订单。拆单比例上升后,成交额和订单数一起增长。

最初怀疑业务真实增长,源端支付金额却没有同步上涨。回查发现父交易金额与履约分配金额同时进入成交指标。

旧验收只检查单号唯一,没有检查业务对象类型,也没有用资金与交易事实做同口径交叉核对。修复应分开事实来源,给每个指标声明计数对象,并检查父子金额上卷关系。

不能简单删除所有父单或所有子单。删除哪一层取决于当前指标,否则成交报表修好了,履约报表却可能失去必要明细。

重新拆分与退款,才是模型的压力测试

原履约子单取消后重新拆出两张新单,如果旧关系仍被认为有效,交易金额又会被分配一次。需要区分历史关系与当前有效关系,保留取消原因和版本衔接。

退款还可能只退某个商品行的一部分数量,或退运费而不退商品。将退款仅关联父订单后平均分给所有子单,会把未退款商品也误标为退款。

验收可按交易明细检查分配数量是否超过可履约数量,按金额检查分摊是否守恒,并核对没有履约、部分履约、取消重建和部分退款等路径。

但守恒也要选正确金额口径:交易含优惠前金额与支付实收不必相等,退款前后金额也不同。先解释差异组成,再建立等式,不能把所有金额强行要求一致。

模型的价值,是让一个业务对象无论怎么拆、怎么合,都能回到原始购买、执行过程和资金结果,而不是用越来越多的去重条件修报表。

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