FDE 落地手记 · 03

经营看板上线以后,最常见的一类争论是:“为什么你的数字和我的不一样?”

运营在看支付金额,仓库在看出库数量,财务在看结算收入;有人按下单时间汇总,有人按发货时间,有人按退款发生时间。同一个词背后,可能是完全不同的数据集合。

在多渠道业务中,FDE 需要把这些差异翻译成明确的指标规则,让页面、报表和 AI 查询遵循同一份定义。

一、先回答粒度问题,再写计算公式

每一张事实表都需要说明“一行代表什么”。一行可能代表主订单、子订单、订单商品、退款事件、出库明细、库存快照或资金流水。

例如,一张订单有两个商品,一笔售后分两次退款,一次出库拆成两个包裹。直接把三张明细表关联起来,订单金额可能被重复多次;重复之后的图表依然可以很平滑,很难靠肉眼发现。

设计指标之前,至少写清以下几项:

维度 必须明确的问题
主体 哪个平台、店铺、公司或渠道?
业务粒度 一行是订单、商品、事件还是快照?
计量单位 元、分、件、单还是人数?
时间依据 支付、发货、退款、入库还是结算时间?
纳入条件 什么状态计入,取消或测试记录如何排除?
观察范围 截止哪一天,迟到数据怎样补回?

“销售额”只有放进这些限定条件里,才会成为可计算、可比较的指标。

二、为关键指标建立一份契约

以下是一个退货数量指标的定义示例。它只是说明结构,不代表各平台都具备同样的数据能力:

metric_id: shipped_cohort_return_qty_rate
version: 1
unit: ratio
grain: channel_sku_shipment_cohort
denominator: eligible_shipped_quantity
numerator: returned_quantity_linked_to_same_shipment_cohort
time_axis: shipment_date
observation: explicit_cutoff_and_window
exclusions:
  - cancelled_before_shipment
  - duplicated_events
quality_states:
  - complete
  - immature
  - missing_source
  - partially_unlinked
owner: designated_business_owner

契约还应记录来源字段、查询逻辑、负责人、确认日期和变更说明。一个字段的注释可以解释它是什么,指标契约则解释它如何被使用。

金额退款率和件数退货率应使用不同指标标识;订单数和商品件数也不能混用。名称越接近,越需要写出差异。

三、区分两种很容易混淆的退货分析

假设一个虚构例子:9 月发出 100 件,其中 10 件在 10 月退回仓库。

  • 分析“9 月发出的货后来退了多少”,应把这 10 件关联回 9 月发货批次,并说明观察截止时间。
  • 分析“10 月退货入库给仓库带来多少工作量”,应把这 10 件放在 10 月入库事件中。

两种分析都可能有用,但含义不同。用“10 月收到的退货”直接解释“10 月发出的货的质量”,会混入此前批次。

如果某渠道无法关联原始发货记录,可以单独展示收货月或入库月的退货情况,说明关联缺失。不能把无法关联解释为没有退货,也不应与已完成原始归因的渠道悄悄汇总成同一种指标。

平台经营数据、ERP 履约数据和财务结算数据,都应保持各自的业务含义。尤其要区分向平台仓供货与终端消费者成交。

四、关联前先检查基数,避免金额被放大

下面的 SQL 展示“先汇总退款事件,再关联订单”的思路。它假设订单主表在复合键上唯一,币种一致,且退款状态、口径和时间条件已事先确定:

WITH refunds_per_order AS (
  SELECT platform_id, shop_id, order_id,
         SUM(refund_amount_minor) AS refund_amount_minor
  FROM eligible_refund_events
  GROUP BY platform_id, shop_id, order_id
)
SELECT o.platform_id, o.shop_id,
       SUM(o.paid_amount_minor) AS paid_amount_minor,
       SUM(COALESCE(r.refund_amount_minor, 0)) AS refund_amount_minor
FROM unique_orders o
LEFT JOIN refunds_per_order r
  ON o.platform_id = r.platform_id
 AND o.shop_id = r.shop_id
 AND o.order_id = r.order_id
GROUP BY o.platform_id, o.shop_id;

这里的 COALESCE 只适用于“退款来源已完整取得、该订单确实没有匹配退款”的情况。若整份退款数据缺失,应在数据质量层阻止它被当成零退款。

如果需要按 SKU 分析,退款也必须具有商品级关联,或使用明确确认的分配规则。订单级退款金额不能简单复制给订单中的每个 SKU。

对每次关联,都可以记录关联前后行数、唯一键数、金额合计、未匹配数量和重复匹配数量。发生非预期变化时先检查基数,再解释业务原因。

五、渠道和 SKU 映射也有时间版本

同一个商品可能有平台商品 ID、平台 SKU、商家编码、ERP 条码和内部产品系列;同一家店铺也可能改名、迁移或改变归属。

映射表建议至少包含:来源系统、来源标识、目标标识、生效时间、失效时间、确认人和确认状态。

当映射变化时,应按业务事件发生时适用的版本计算历史数据,或明确记录重算。否则今天修改一次商品归属,去年报表可能在没有说明的情况下发生变化。

未确认映射应进入异常清单,保留其金额和数量,便于评估影响。直接丢弃会让总表变小,随意归入“其他”则可能掩盖渠道问题。

六、把校验放在数据链路里

我会优先建立以下校验:

  1. 同一来源的重复导入不会增加事实数量。
  2. 按互斥且覆盖完整的渠道分组后,可以回到总额;未归属部分单独列示。
  3. 汇总与明细采用同一批数据和同一规则版本。
  4. 数据缺失、批次未成熟和业务零值能被分别识别。
  5. 原始记录修正或迟到事件到达后,能定位受影响的时间段并重算。

对于自动采集的数据,可以保留原始文件与批次,再进行标准化、映射和指标加工。这样遇到数字争议,能够沿着指标、转换、批次一直查到来源记录。

七、AI 查询应当复用已经确认的指标

当用户问“最近一周退货率是多少”,系统可能仍需要确认渠道、件数或金额口径、时间依据和观察截止日期。

比较稳妥的做法是让 AI 选择受控指标、补齐参数、调用查询,并在回答里带出定义和数据状态。重要计算尽量复用确认过的实现,避免每次临时生成另一套算法。

维护一份清楚的指标契约,可以同时减少页面开发、报表核对和 AI 问答中的歧义。这类基础工作很少出现在演示的第一屏,却决定了业务能否长期相信系统。


FDE 落地手记 · 系列阅读

关于作者:冷晓磊 / XiaoLei

代码世界的构建师,现实生活的悠游者。