首页/数据/数仓建模速查/SCD 类型 3:增加前值列
维度与事实设计149 条

SCD 类型 3:增加前值列

保留当前值与上一值两列(如 current_tier / previous_tier),历史深度只有一跳,表宽固定不随变更增长。

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

类型 3 是什么

类型 3 在同一行上增加一列保存上一版本的值,例如同时有 tier 与 previous_tier、address 与 previous_address。它的历史深度只有一跳,表宽固定、不随变更次数增长,查询时不需要过滤生效区间。适合变更很少且只关心「最近一次迁移」的场景,例如客户等级调整、地区归属变更前后对比。它无法回答「上上次是什么」,需要多跳历史时应改用类型 2 拉链。

基本信息

历史深度仅保留上一版本,一跳
实现增加前值列,更新时先搬再覆盖
适用变更少、只关心最近一次迁移
限制多次变更后旧值被覆盖,更早历史丢失
配套列通常再配一列变更时间,说明前值对应何时

典型使用场景

  • 客户等级迁移:只看从哪一档升到哪一档,用于当期营销分析
  • 区域重划:行政区或销售区域调整前后对比
  • 价格档位调整:只关心最近一次调价前后的档位
  • 费率变更:上一次费率与当前费率对比,做差异测算
  • 归属变更:客户从 A 团队转到 B 团队,看最近一次转移
  • 折中方案:业务只要最近一次变化,不必为完整历史承担拉链成本

更新前值

更新前值
-- 更新前先把当前值搬到前值列,再覆盖当前值
UPDATE dim_user
SET    previous_tier = tier,        -- 先搬
       tier          = :new_tier,   -- 再覆盖
       changed_date  = :dt
WHERE  user_id = :id;

-- 查询本次迁移:前值与当前值不同的成员
SELECT user_id, previous_tier, tier, changed_date
FROM   dim_user
WHERE  previous_tier IS NOT NULL
  AND  previous_tier <> tier;   -- 只看最近一次发生过变化的成员

类型 3 与类型 2 对比

对比项类型 3类型 2 拉链
历史深度一跳完整历史
表宽与行数列数固定,行数不变行数随变更次数增长
查询复杂度无需区间过滤需按生效区间或当前标志过滤
多次变更旧值被覆盖,更早历史丢失逐次版本都保留
改造成本加列即可需要重建版本行与增量作业
类型 3 最常见的误判是「先按类型 3 做,将来不够用再改成类型 2」:等到需要多跳历史时,中间几次变化没有任何记录,只能回溯源系统日志,改造成本远高于一开始就选类型 2。属性如果可能被用于历史归因,就该一开始就评估这一点。

易错点

  • 需要多跳历史却发现类型 3 不够用:更早的中间值已丢失,只能回溯源端日志
  • 对频繁变更属性用类型 3:前值很快被覆盖,参考意义下降
  • 更新时先覆盖当前值再搬前值:两条语句写反了,前值等于当前值,迁移信息永久丢失
  • 前值列不带变更时间:只知道变过,无法判断前值对应哪个时点
  • 多个属性各自加前值列:列数成倍增长,宽表膨胀且维护易错

数据来源与参考

  • 维度建模工具箱:缓慢变化维
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌