[ SQL ] 数据仓库中两张拉链表间关联

背景:

  1.因为业务系统中存在更新表数据的情况,且总数据量不大,数仓ODS层中采用了对事实表进行拉链的操作。

  2.现在需要在ODS层中对多张拉链表进行关联,为了以后追数方便,需要先给出一个全量更新的脚本。

 

设计两个表结构,暂时称为“事实表(odstr)”和“维度表(odsdim)”:

drop table if exists odstr;
create table odstr(
num int,                   -- 序号
id int,                    -- 编号
code varchar(100),         -- 编码(维度表中码值)
create_dt varchar(100),    -- 创建时间(事实数据的入库时间)
modify_dt varchar(100),    -- 修改时间(同上)
start_dt varchar(100),     -- 数据生效时间(拉链开始时间)
end_dt varchar(100)        -- 数据失效时间(拉链结束时间)
);

drop table if exists odsdim;
create table odsdim(
num int,                  -- 序号
code varchar(100),        -- 编码
name varchar(100),        -- 编码的值
start_dt varchar(100),    -- 数据生效时间
end_dt varchar(100)       -- 数据失效时间
);

 

场景模拟数据:

  1)码值先于事实数据发生,即在事实表中发生之前就已经存在很多维度的拉链数据,且有一条以上的拉链数据在事实数据插入前已经失效。

-- 事实表数据
insert into odstr values(1, 1001, 'A', '2021-01-01', '2021-10-05', '2021-10-05', '2021-10-17');    
insert into odstr values(2, 1001, 'A', '2021-01-01', '2021-10-18', '2021-10-18', '2021-10-20');
-- 维度表数据
insert into odsdim values(8, 'A', 'T110', '2021-10-01', '2021-10-02');  -- 不会被关联出
insert into odsdim values(1, 'A', 'T110', '2021-10-13', '2021-10-17');  -- 被事实表 1 关联出
insert into odsdim values(2, 'A', 'T120', '2021-10-18', '9999-12-31');  -- 被事实表 2 关联出

结果用编号展示应为:

      odstr  <-> odsdim

        1    1

        2    2

   2)事实数据发生后,码值先后发生多次变化

-- 事实表数据
insert into odstr values(3, 1002, 'B', '2021-01-01', '2021-10-21', '2021-10-21', '9999-12-31');
-- 维度表数据
insert into odsdim values(9, 'B', 'T140', '2020-10-17', '2021-10-16'); -- 不会被关联出
insert into odsdim values(3, 'B', 'T140', '2021-10-17', '2021-10-25');
insert into odsdim values(4, 'B', 'T140', '2021-10-26', '2021-10-30');
insert into odsdim values(5, 'B', 'T140', '2021-10-31', '9999-12-31');

结果用编号展示应为:

      odstr  <-> odsdim

        3    3
        3    4
        3    5

 

SQL:

select a.num, b.num , b.name, a.code, b.code 
,case when a.start_dt <= b.end_dt and a.end_dt   >= b.end_dt  then 1 else 0 end as tj1  -- 条件1
,case when b.start_dt <= a.end_dt and b.end_dt > a.end_dt  then 1 else 0 end    as tj2  -- 条件2
from odstr a 
left join odsdim b 
on a.code = b.code 
and (
        (a.start_dt <= b.end_dt and a.end_dt   >= b.end_dt) 
     or 
         (b.start_dt <= a.start_dt and b.end_dt > a.start_dt )
    )

;

 

 

 

 

 

posted @ 2021-11-17 17:23  1440min  阅读(877)  评论(0编辑  收藏  举报