首页/数据/数仓建模速查/退化维度 Degenerate Dimension
建模基础69 条

退化维度 Degenerate Dimension

订单号、发票号这类无独立属性的业务编号,直接存在事实表上作为退化维度,不单独建维度表。

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

退化维度是什么

退化维度指订单号、发票号、流水号这类没有独立描述属性的业务编号:它们不单独建维度表,而是直接作为字段留在事实表里。它们承担的是单据级下钻与追溯——按订单号查到全部明细行、按发票号核对金额。之所以叫「退化」,是因为这类编号除自身之外没有别的属性,为它单独建表只会多一次 join,不带来任何分析价值。

基本信息

典型字段订单号、发票号、流水号、合同号
存放位置事实表字段,不建维度表
用途单据级下钻、去重、与业务系统核对
粒度要求必须与事实表粒度一致
例外编号上确需挂属性(如发票类型、开票人)时才拆成维度表

典型使用场景

  • 单据追溯:按订单号一次性拉出全部明细行与金额
  • 去重统计:按订单号计数得到订单数,而不是按明细行计数
  • 跨表核对:与业务系统的订单号逐单比对,定位差异单据
  • 退款关联:退款事实用原订单号关联到原交易,做净额查看
  • 明细下钻:报表从汇总钻到订单,再钻到订单商品行
  • 空值占位:源端缺单号时用显式占位值,避免 NULL 参与分组

退化维度用法

退化维度用法
-- 订单号留在事实表,按它做单据级汇总
SELECT order_no, sum(amount) AS amt
FROM   fact_order_detail
GROUP  BY order_no;

-- 订单数按订单号去重,不能按明细行计数
SELECT count(distinct order_no) AS order_cnt,
       count(1)                 AS detail_row_cnt
FROM   fact_order_detail
WHERE  dt = '2026-10-11';

-- 与业务系统逐单核对差异
SELECT f.order_no, f.amt, s.amt AS src_amt
FROM   fact_order_detail f
JOIN   ods_order s ON f.order_no = s.order_no
WHERE  abs(f.amt - s.amt) > 0.01;

编号类字段的归置

字段归置理由
订单号、发票号退化维度(留事实表)除自身无属性,建表只增 join
合同号 + 合同类型维度表编号上确有可分析的描述属性
支付流水号退化维度用于对账与退款关联
商品编码维度表有品类、品牌等可分析属性
物流单号退化维度或独立事实用于查询物流轨迹,属性少
退化维度的粒度必须与事实表一致:订单商品行粒度的事实表里,同一个订单号会出现多行,按它汇总金额是对的,按它统计行数则是另一回事。若事实表是一订单一行,订单号才是唯一键。混用两种粒度是这类字段最常见的误用。

易错点

  • 给订单号单独建一张无属性维度表:每次查询多一次 join,没有任何分析收益
  • 把退化维度当维度键使用:与真正的维度键混在一列里,粒度混乱难以排查
  • 按订单号统计明细行数当订单数:一单多商品时订单数被放大数倍
  • 退化维度允许为 NULL:分组与去重时 NULL 被合并成一组,结果无法解释
  • 编号上确有属性却硬留在事实表:发票类型、开票人这类属性重复存储且无法统一维护

数据来源与参考

  • Kimball 方法论:退化维度
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌