SCD-2 主数据构建器
根据源表构建缓慢变化维度类型 2(SCD-2) 历史表。普通主表只保留每个键的当前值,而 SCD-2 表会保留键曾经持有的每个值,并为每个值标记其生效的日期范围。这样,您就可以回答时点问题(该客户在交易当天属于哪个区域?),而不仅仅是他们现在属于哪个区域?
每次运行都会将源快照与先前的历史进行比较,对于所跟踪属性发生变化的键,关闭旧版本并开启新版本。表会被重新计算并以原子方式替换,因此使用相同输入重新运行会产生相同的结果。
可将此步骤与 SCD-2 截至日期联接搭配使用,把时点值附加到事实表。
每次运行都会在您携带的列之外输出三个保留列。您无需为它们命名,它们始终是 valid_from、valid_to 和 is_current,您的业务键列和跟踪列不得重用这些名称。
| 列 | 含义 |
|---|---|
valid_from |
此版本生效的日期(包含)。 |
valid_to |
此版本不再生效的日期(不包含)。开放(当前)行带有哨兵上限日期 9999-12-31。 |
is_current |
当前生效的版本为 true,已关闭的历史版本为 false。 |
主数据的当前快照,每个业务键一行,包含当前的属性值。
先前的 SCD-2 表(可选)
Section titled “先前的 SCD-2 表(可选)”上一次运行产生的现有历史表。首次运行时请将其留空(或指向结果表);此步骤随后会从头构建完整的历史,在生效日期为每个源行开启一个版本。
写入重建后历史的位置。必须是表,而不是视图。
生效日期和选项
Section titled “生效日期和选项”每次运行都使用单个生效日期标记其变更。请以以下两种方式之一(且仅一种)提供,两者都提供或都不提供均会报错。
- 生效日期列:源中保存生效日期的列。每个源行上的值必须相同(快照截至同一个日期)。
- 生效日期:固定的
YYYY-MM-DD日期,或诸如{current_month}的变量,应用于整个运行。
其他选项:
- 开放区间上限日期:写入开放行
valid_to的哨兵值。默认为9999-12-31,很少有理由更改它,并且它必须与 SCD-2 截至日期联接所使用的上限日期一致。 - 缺失时关闭:启用后,从源中消失的键,其开放版本会在生效日期关闭(该键被视为已停用)。禁用时(默认),缺失的键保留其现有的开放版本,因此历史不会因部分提取而丢失。
如果固定的生效日期或开放区间上限日期不是 YYYY-MM-DD 格式的有效日期,或生效日期不早于上限日期,步骤会拒绝保存。以变量形式给出的日期不会被检查。
使用检查源列出源列,然后为每一列标记角色:
| 角色 | 含义 |
|---|---|
| 业务键 | 在不同时间点标识一行的自然键(例如 customer_id)。至少需要一个。值在源中必须唯一且非空。 |
| 跟踪属性 | 其变化会开启新版本的属性(例如 region)。至少需要一个。 |
| (沿用) | 未标记的列会原样复制到每个版本上,其本身不会触发新版本。 |
提供先前的表时,此步骤仅将源快照与当前版本(从不包括已关闭的历史)进行比较,并按键判断:
| 情形 | 结果 |
|---|---|
| 跟踪的属性未变 | 无操作,开放版本保持原样。 |
| 跟踪的属性已变 | 开放版本在生效日期关闭,并插入一个新的开放版本。 |
生效日期等于开放版本的 valid_from |
视为当日重述,跟踪的值会就地覆盖,而不是创建零宽度区间。 |
| 键在源中缺失 | 保持开放(如果启用了缺失时关闭,则在生效日期关闭)。 |
以下防护措施会让运行停止,而不是悄悄地破坏历史:
- 乱序日期会被拒绝。 生效日期必须晚于每个受影响键当前的
valid_from。如果回溯日期的运行会使区间颠倒,则会报错失败,而不是产生负宽度的版本。 - 重复的源键会被拒绝。 源在业务键上必须唯一;重复键(或空键)会导致失败,而不是被悄悄去重。
- 变更检测对空值安全,因此值变为空或从空变为其他值都会被正确记录为变更。
跟踪每个客户随时间所属的区域。
源:customer_master(截至 2026-01-01):
| customer_id | region | segment |
|---|---|---|
| C1 | West | SMB |
| C2 | East | Enterprise |
首次运行:源表 = customer_master,先前的 SCD-2 表 = 空,结果表 = customer_scd2,生效日期 = 2026-01-01,业务键 = customer_id,跟踪属性 = region(segment 未标记,沿用)。
首次运行后的 customer_scd2:
| customer_id | region | segment | valid_from | valid_to | is_current |
|---|---|---|---|---|---|
| C1 | West | SMB | 2026-01-01 | 9999-12-31 | true |
| C2 | East | Enterprise | 2026-01-01 | 9999-12-31 | true |
现在 C1 迁移到了 Central 区域。源:customer_master(截至 2026-04-01):
| customer_id | region | segment |
|---|---|---|
| C1 | Central | SMB |
| C2 | East | Enterprise |
第二次运行:表角色相同,先前的 SCD-2 表 = customer_scd2,生效日期 = 2026-04-01。
第二次运行后的 customer_scd2:
| customer_id | region | segment | valid_from | valid_to | is_current |
|---|---|---|---|---|---|
| C1 | West | SMB | 2026-01-01 | 2026-04-01 | false |
| C1 | Central | SMB | 2026-04-01 | 9999-12-31 | true |
| C2 | East | Enterprise | 2026-01-01 | 9999-12-31 | true |
C1 的 West 版本在 2026-04-01 关闭,并开启了 Central 版本。由于采用半开区间,日期为 2026-04-01 的交易属于 Central,而不是 West。C2 未发生变化,保持不动。
- SCD-2 截至日期联接:将时点值附加到事实表。
- Dimension Load 步骤:从表加载层次结构。