首页/数据/数据工程与 ETL 速查/桥接表处理多值维度

桥接表处理多值维度

当一条事实对应多个维度取值(一笔订单多张优惠券、一个客户多个标签)时,事实与维度是多对多关系;桥接表存两者中间关系并按需加权,避免事实行被复制放大。

桥接表处理多值维度

当一条事实对应多个维度成员时(一笔订单用了多张优惠券、一个客户打了多个标签),事实与维度之间是多对多关系。直接连接会让事实行被复制:一笔 100 元的订单关联 3 张券,金额就被算成 300。桥接表(bridge table)在两者之间存关系行,通常带一个权重用于按主次分摊度量,这样既能做“命中哪些券”的覆盖分析,也能做“按券分摊金额”的贡献分析。若只需要命中关系而不需要分摊,用无事实事实表更简单。

基本信息

解决的问题一条事实对应多个维度成员(多对多)
结构事实代理键 × 维度代理键,可加权重列
权重作用按主次分配度量,避免金额被重复累加
替代方案在维表存数组或字符串列表,简化查询但分析能力受限
粒度要求桥接表一行代表一条关系,需在表说明中写明

典型使用场景

  • 订单与优惠券:一笔订单使用多张券,需要同时做覆盖与金额分摊
  • 商品与标签:一个商品属于多个标签,分析标签维度的销售表现
  • 处方与药品:一张处方包含多种药品,统计药品用量与费用分摊
  • 企业与行业分类:一家企业隶属多个行业,需按行业做加权统计
  • 内容与人群包:一篇内容投放进多个人群包,评估各包的贡献

桥接表结构

桥接表结构
-- 桥接表:一行一条 订单与优惠券 的关系,权重用于分摊金额
CREATE TABLE bridge_order_promo (
  order_sk BIGINT,
  promo_sk INT,
  weight   DECIMAL(5,2)   -- 分摊权重,同一 order_sk 的权重之和应为 1
);

-- 按权重分摊订单金额
SELECT p.promo_name,
       SUM(f.pay_amount * b.weight) AS allocated_amt
FROM fact_order f
JOIN bridge_order_promo b ON f.order_sk = b.order_sk
JOIN dim_promo p ON b.promo_sk = p.promo_sk
GROUP BY p.promo_name;

-- 覆盖口径(只关心命中):不计权重,按主体去重
SELECT COUNT(DISTINCT b.order_sk) AS order_cnt FROM bridge_order_promo b;

两种口径对照

口径连接方式结果含义注意点
覆盖分析桥接表连接后按主体去重命中该维度的主体数不要直接 SUM 金额
分摊分析按权重加权求和各维度按主次分摊的度量权重之和需归一到 1
简单命中无事实事实表只有关系,无度量实现最简单
不设权重直接连接桥接表会把订单金额按券数量重复计算:做覆盖分析时按主体去重,做金额分析时必须用权重。
权重之和不为 1 时,分摊后的金额合计与订单总额不一致;建模时要加一条校验,把偏离超过容差的订单找出来。
每个聚合场景各建一张桥接表会让关系口径分叉:优先用一张桥接表加权重适配多种口径,确有必要再拆分。

易错点

  • 桥接表不带权重直接连接,金额被重复累加,总额远超实际且随券数量变化
  • 每个聚合场景各建一张桥接表,事实与维度关系口径不一致,核对时对不上
  • 权重之和不为 1 且无校验,分摊金额与订单总额长期存在差异
  • 把多对多关系直接压进事实表(一行一张券),事实表粒度被破坏,订单数被放大

数据来源与参考

  • Kimball《The Data Warehouse Toolkit》多值维度与桥接表
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌