首页/数据/数仓建模速查/案例:零售门店销售域建模
建模基础69 条

案例:零售门店销售域建模

门店零售以「销售小票行」为事务事实:维度为日期/门店/商品/会员/促销;退货用负数量与负金额并入同一事实,净销售 = sum。

数仓建模速查数据更新于 2026-10-13

零售销售域怎么落模型

门店零售的典型事实是销售小票行:一行代表某张小票上的一个商品行,维度是日期、门店、商品、会员、促销,度量是数量、销售金额与折扣金额。退货不另建表,而是用负数量、负金额并入同一张事实表,这样净销售就是一次求和,避免多表相减带来的口径分歧。

基本信息

事实粒度小票行,票据号加行号唯一
常用维度日期、门店、商品、会员、促销、收银员
度量数量、销售金额、折扣金额、成本金额
退货处理负数量与负金额并入同一事实
常见平台Hive 与 Spark SQL 按日分区,Doris 承接明细查询

典型使用场景

  • 日常经营报表:按门店与日期看销售额、客流与客单价,全部来自同一张事实表
  • 商品结构分析:从类目、品牌下钻到单品,销量与折扣力度同步可见
  • 促销效果评估:用促销维度对比活动期与非活动期的销量与毛利
  • 会员消费分析:小票行关联会员维度,计算复购率与客单分布
  • 库存联动:小票行按门店与商品汇总后与库存快照勾稽

零售星型事实表

零售星型事实表
-- 小票行粒度:票号加行号唯一,退货行数量金额为负
CREATE TABLE fact_retail_sale (
  dt_key       int COMMENT '日期键',
  ticket_no    string COMMENT '小票号',
  line_no      int COMMENT '行号',
  store_sk     bigint COMMENT '门店代理键',
  product_sk   bigint COMMENT '商品代理键',
  member_sk    bigint COMMENT '会员代理键,非会员走未知成员',
  promo_sk     bigint COMMENT '促销代理键',
  qty          int COMMENT '数量,退货为负',
  sales_amt    decimal(18,2) COMMENT '销售金额,退货为负',
  discount_amt decimal(18,2) COMMENT '折扣金额'
) PARTITIONED BY (dt string) STORED AS ORC;

指标口径对照

指标正确算法常见错误
销售额对小票行金额求和退货存在另一张表,净销售漏算
客单价票级金额除以去重后票数按行级平均,客单价被行数稀释
客流量按小票号去重计数按会员去重,非会员客流被丢掉
退货率负金额绝对值除以正金额只数退货运单笔数,金额口径不可比
票头信息(会员、时间、收银员)冗余在每一行上是合理的退化维度做法:查询不必回表关联票头,代价只是小票号重复存储占用空间。
非会员交易必须落到未知成员而不是留空,否则与会员维度关联时丢行,客流量与会员渗透率会同时失真。

易错点

  • 票级与行级指标混算:客单价按行平均,数字整体偏低
  • 退货另建一张表:净销售要跨表相减,任一侧延迟加载口径立刻不一致
  • 小票号在不同门店会重复:只按票号去重,跨店小票被错误合并
  • 折扣金额与销售金额口径不清:一个含折扣一个不含,毛利计算直接错
  • 非会员交易留空值而非未知成员:关联后丢行,客流与渗透率同时失真

数据来源与参考

  • Kimball Group:零售行业模型(Retail Sales)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌