如何用SQL实现全量切片表转成拉链表
必须是写SQL的方式,不能用其他代码实现。
现有全量切片表样数据
切片日期 | 主键编号 | 状态 |
---|---|---|
20211201 | A | 01 |
20211205 | A | 01 |
20220215 | A | 02 |
20220228 | A | 03 |
20220315 | A | 01 |
20220331 | A | 01 |
20220420 | A | 01 |
20220425 | A | 02 |
20220430 | A | 01 |
20211201 | B | 01 |
20211203 | B | 01 |
20220131 | B | 02 |
要一次性转换成拉链数据:要求不能用脚本重复循环跑SQL
转换成拉链表的数据为以下所示,30001231表示长期有效
主键编号 | 开始日期 | 状态 | 结束日期 |
---|---|---|---|
A | 20211201 | 01 | 20220215 |
A | 20220215 | 02 | 20220228 |
A | 20220228 | 03 | 20220315 |
A | 20220315 | 01 | 20220425 |
A | 20220425 | 02 | 20220430 |
A | 20220430 | 01 | 30001231 |
B | 20211201 | 01 | 20220131 |
B | 20220131 | 02 | 30001231 |
我现在主要问题是如何通过单纯的SQL,一次性进行转换。
若不是一次性,通过循环拉链算法脚本的话,我有样例:
--把每天跑批日期的切片数据按照拉链的形式插入到临时表中,表示当天新的拉链数据
INSERT INTO 临时表_当前
SELECT
主键编号
,跑批日期
,状态
,'30001231'
FROM 切片表
WHERE 切片日期=跑批日期
;
--可以对当天进行重复跑批的操作
DELETE FROM 目标表
WHERE 开始日期='变量(跑批日期)'
AND 结束日期='30001231';
UPDATE 目标表
SET 结束日期='30001231'
WGERE 结束日期='变量(跑批日期)';
--找到与目标表中生效的数据不同的数据
INSERT INTO 临时表_插入
SELECT
主键编号
,开始日期
,状态
.结束日期
FROM 临时表_当前
WHERE NOT EXISTS
(
SELECT 1
FROM 目标表
WHERE 临时表_当前.主键编号=目标表.主键编号
AND 临时表_当前.状态=目标表.状态
AND 目标表.结束日期=‘30001231’
);
--更新目标表中的数据,对更新的数据进行关链
UPDATE 目标表
SET END_DT='跑批日期'
WHERE END_DT='30001231'
AND EXISTS
(SELECT 1
FROM 临时表_插入
WHERE 目标表.主键编号=临时表_插入.主键编号
);
--新增的数据插入目标表中
INSERT INTO 目标表
SELECT
主键编号
,’跑批日期‘
,状态
,'30001231'
FROM 临时表_插入;
然后将以上的SQL,封装下,按照日期每天一次顺序跑批,也能完成切片转换成拉链的算法。
但是此方法碰到要处理10年的数据话,就要跑10年的每一日的批次,有点慢。
因此有大佬能一次性写个SQL,直接完成切片转换成拉链的么?
create table tmp_data_test2
(
ts string,
id string,
status string
);
insert into tmp_data_test2
values
('20211201','A','01'),
('20211205','A','01'),
('20220215','A','02'),
('20220228','A','03'),
('20220315','A','01'),
('20220331','A','01'),
('20220420','A','01'),
('20220425','A','02'),
('20220430','A','01'),
('20211201','B','01'),
('20211203','B','01'),
('20220131','B','02');
select
id,ts as start_date,status,
lead(ts,1,'30001231') over(partition by id order by ts) as end_date
from(
select
ts,id,status,
row_number() over(partition by id,status,group1 order by ts) as rank2
from(
select
ts,id,status,
floor(rank1-rank2) as group1
from(
select
ts,id,status,
row_number() over(partition by id order by ts) as rank1,
row_number() over(partition by id,status order by ts) as rank2
from tmp_data_test2
)t2
)t3
)t4
where rank2=1;
基于你给的样例数据,全量数据可以这样实现
单纯的sql一次性转换应该实现不了,正常的还是需要这种方法
全量表、增量表、拉链表如何生成?
https://blog.csdn.net/weixin_43648241/article/details/108961783