缓慢变化维,拉链表


1 原文

解决缓慢变化维—拉链表
https://blog.youkuaiyun.com/panfelix/article/details/107062349
SCD2维度更新,如何紧急将hive脚本 改成 Oracle脚本
https://blog.youkuaiyun.com/u014337370/article/details/109542827

2 小结

1,缓慢变化维的缓慢是相对与事实表而言,维度表的变化速度比事实表缓慢

2,随时间变化的维度表称为缓慢变化维

3 缓慢变化维

比如 一张表 四个字段 有ID,姓名,年龄,修改时间四字段,
在原有表的基础上加上额外两列,
------------1 生效时间(dw_start_date)
------------2 失效时间(dw_end_date)
第一个表示某条数据生命周期的起始时间,即生效日期
第二表示某条数据生命周期的结束时间,即失效日期
-----------存在当dw_end_date为9999-12-31,表示这条数据最新

4 增量抽取当日新增数据和当日修改数据同步到ods层

5 编写sql重新计算dw_end_date

6 拉链表实现步骤,使用当天最新的数据union all 历史数据

7 查询拉链表

查询拉链表
1、获取2019-12-20日的历史快照数据
select *
from demo.dw_product_2
where dw_start_date <= '2019-12-20'
  and dw_end_date > '2019-12-20'
order by goods_id;

2、获取最新的商品快照数据
select *
from demo.dw_product_2
where dw_end_date = '9999-12-31'
order by goods_id;

8 其他缓慢变化维例子_1

--准备数据
create table dim_emp
(
    emp_sk     number,       --代理键
    emp_id     varchar2(50),--员工编号
    emp_name   varchar2(50),--员工姓名
    empno      varchar2(50), --部门
    emp_gw     varchar2(50),--岗位
    begin_date date,         --生效日期
    end_date   date,         --失效日期
    row_status number        --行有效状态
);

create table emp_table
(
    emp_id      varchar2(50),--员工编号
    emp_name    varchar2(50),--员工姓名
    empno       varchar2(50), --部门
    emp_gw      varchar2(50), --岗位
    last_update date --更新日期
);

SELECT *
FROM dim_emp;
SELECT *
FROM emp_table;


insert into dim_emp
values ('1', '001', '张三', '财务部', '财务经理', date'2020-02-01', date'9999-12-31', 1);
insert into dim_emp
values ('2', '002', '王五', '销售部', '销售员', date'2020-02-01', date'9999-12-31', 1);
insert into dim_emp
values ('3', '003', '赵四', '人力部', '人力经理', date'2020-02-01', date'9999-12-31', 1);
insert into dim_emp
values ('4', '004', '李青', '生产部', '车间主任', date'2020-02-01', date'9999-12-31', 1);
commit;

insert into emp_table
values ('001', '张三', '财务部', '财务经理', date'2020-03-01'); --不变
insert into emp_table
values ('002', '王五五', '销售部', '销售员', date'2020-03-01'); --姓名改变
insert into emp_table
values ('003', '赵四', '管理部', '总经理', date'2020-03-01'); -- 部门和岗位改变
insert into emp_table
values ('004', '李青', '生产部', '车间主任', date'2020-03-01'); --不变
insert into emp_table
values ('005', '钱七', '物流部', '快递员', date'2020-03-01'); --新增
commit;


--SCD2更新逻辑
select row_number() over (order by t1.emp_id) + t3.max_sk as emp_sk -- 生成代理键
     , t1.emp_id
     , t1.emp_name
     , t1.empno
     , t1.emp_gw
     , case
           when t1.last_update is null then date'2020-03-01' --正常情况应该是系统时间-1天
           else last_update end                           as begin_date
     , date'9999-12-31'                                      end_date
     , 1                                                  as row_status
from emp_table t1 --源表
         left join -- t1 左连接 t2
    dim_emp t2 --维度表
                   on t1.emp_id = t2.emp_id
         cross join
         (select max(emp_sk) as max_sk from dim_emp) t3 --获取维表最大代理键
where t2.emp_sk is null
   or t2.emp_name != t1.emp_name
   or t2.empno != t1.empno
   or t2.emp_gw != t1.emp_gw
--维表代理键为空或SCD2的字段不相等
--获取到源表相对于维表,新增或变化的数据
union all
select t4.emp_sk
     , t4.emp_id
     , t4.emp_name
     , t4.empno
     , t4.emp_gw
     , t4.begin_date
     , case
           when t4.emp_name != t5.emp_name --SCD2字段不相等则修改失效时间
               or t4.empno != t5.empno
               or t4.emp_gw != t5.emp_gw
               then date'2020-03-01'
           else end_date end as end_date
     , case
           when t4.emp_name != t5.emp_name --SCD2字段不相等则修改失效时间
               or t4.empno != t5.empno
               or t4.emp_gw != t5.emp_gw
               then 0
           else 1 end        as row_status
from dim_emp t4 --维表
         left join --t4 左连接 t5
    emp_table t5--源表
                   on t4.emp_id = t5.emp_id

9 其他缓慢变化维例子_2

INSERT OVERWRITE TABLE dw.dim_table --维表
SELECT
      ROW_NUMBER() OVER (t1.emp_code,t1.job_code) + max_sk AS sk_emp_info  --生成外键
    , t1.emp_name  --SDC2字段
    , t1.emp_code
    , t1.job_name ----SDC2字段
    , t1.jobt_code
    , CASE
        WHEN t1.last_update_dt IS NOT NULL
            THEN t1.last_update_dt
        ELSE DATE_FORMAT( DATA_SUB(CURRENT_DATE,1),'yyyyMMdd') --当前的前一天
      END AS valid_start_dt --生效时间
    , '99991231' AS valid_end_dt --失效时间
    , 'Current' AS row_status --行状态
--3、从【源表】获取相对于【维度表】变化/增加的数据:步骤1 [left join] 步骤2
FROM
---1、获取源数据
(
    SELECT
         emp_name  --SDC2字段
        ,emp__code --持久键
        ,job_name  --SDC2字段
        ,job_code --持久键
        ,last_update_dt
    FROM
        ods.ods_table
) t1
---2、获取维度数据
LEFT OUTER JOIN
(
    SELECT
         sk_emp_info  --代理键
        ,emp_name  --SDC2字段
        ,emp__code --持久键
        ,job_name ----SDC2字段
        ,job_code --持久键
    FROM
       dw.dim_table
) t2
--持久键 连接
ON t1.emp__code = t2.emp__code
    AND t1.job_code = t2.job_code
--获取维度表最大的外键,以便为新增数据生成外键
CROSS JOIN
(
    SELECT
        COALESCE(MAX(sk_emp_info),0) AS max_sk
)dim_sk_tmp
WHERE t2.sk_emp_info is null
    OR t1.emp_name != t2.emp_name
    OR t1.job_name != t2.job_name

UNION ALL

-- 4、从【维度表】获取"相对于【源表】有变化的数据":步骤2 [left outer join] 步骤1
SELECT
      t3.sk_emp_info
    , t3.emp_name
    , t3.emp_code
    , t3.job_name
    , t3.job_code
    , t3.valid_start_dt
    , CASE
        WHEN t3.emp_name != t4.emp_name
            OR  t3.job_name != t4.job_name
                THEN t4.last_update_dt
        ELSE t3.valid_end_dt  --将维表SCD2字段有变化的某行的有效截止时间valid_end_dt 修改成源表的更新时间
      END AS valid_end_dt
    , CASE
        WHEN t3.emp_name != t4.emp_name
            OR  t3.job_name != t4.job_name
                THEN 'Expired' --将维表SCD2字段有变化的某行的状态row_status标记为“失效”--Expired
        ELSE t3.row_status
      END AS row_status
FROM
--2、获取维度数据
(
    SELECT
         sk_emp_info  --代理键
        ,emp_name  --SDC2字段
        ,emp__code --持久键
        ,job_name ----SDC2字段
        ,job_code --持久键
    FROM
       dw.dim_table
) t3
--1、获取源数据
LEFT OUTER JOIN
(
    SELECT
         emp_name  --SDC2字段
        ,emp__code --持久键
        ,job_name  --SDC2字段
        ,job_code --持久键
        ,last_update_dt
    FROM
        ods.ods_table
) t4
ON t3.emp_code = t4.emp_code
   AND t3.job_code = t4.job_code

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值