前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >etl算法详解_数据拉链处理什么意思

etl算法详解_数据拉链处理什么意思

作者头像
全栈程序员站长
发布2022-11-03 16:57:27
5360
发布2022-11-03 16:57:27
举报
文章被收录于专栏:全栈程序员必看

所谓拉链,就是记录历史。记录一个事物从开始,一直到当前状态的所有变化的信息。

在历史表中对客户的一生的记录可能就这样几条记录,避免了按每一天记录客户状态造成的海量存储的问题: (NAME)人名 (START-DATE)开始日期 (END-DT)结束日期 (STAT)状态 client 19000101 19070901 H在家 client 19070901 19130901 A小学 client 19130901 19160901 B初中 client 19160901 19190901 C高中 client 19190901 19230901 D大学 client 19230901 19601231 E公司 client 19601231 29991231 H退休在家

上面的每一条记录都是不算末尾的,比如到19070901,client已经在A,而不是H了。所以除最后一条记录因为状态到目前都未改变的,其余的记录实际上在END-DT那天,都不在是该条记录END-DT那天的状态。这种现象可以理解为算头不算尾。

算法:(拉链表算法其实就是以前遇到过的缓慢变化维的其中一种情况,用存储过程实现的话稍微麻烦点。)

1采集当日全量数据到ND(NewDay)表;

2可从历史表中取出昨日全量数据存储到OD(OldDay)表;

3(ND-OD)就是当日新增和变化的数据,也就是当天的增量,用W_I表示;

4(OD-ND)为状态到此结束需要封链的数据,用W_U表示;

5将W_I表的内容全部插入到历史表中,这些是新增记录,start_date为当天,而end_date为max值;

6对历史表进行W_U部份的更新操作,start_date保持不变,而end_date改为当天,也就是关链操作;

下面为具体例子:

[sql] view plain copy

  1. OD(在第一天就等于HIS)
  2. 用户标志 状态 开始时间 结束时间
  3. 1 1 200712 299901
  4. 2 2 200712 299901
  5. 3 3 200712 299901
  6. 4 4 200712 299901
  7. 5 5 200712 299901
  8. ND
  9. 用户标志 状态 开始时间 结束时间
  10. 1 2 200801 299901
  11. 2 2 200801 299901
  12. 3 4 200801 299901
  13. 4 4 200801 299901
  14. 5 6 200801 299901
  15. W_I=ND-OD ( 将W_I表的内容全部插入到历史表中,这些是新增记录 )
  16. 用户标志 状态 开始时间 结束时间
  17. 1 2 200801 299901
  18. 3 4 200801 299901
  19. 5 6 200801 299901
  20. W_U=OD-ND ( 对历史表进行W_U部份的更新操作,start_date保持不变,而end_date改为当天 )
  21. 用户标志 状态 开始时间 结束时间
  22. 1 1 200712 299901
  23. 3 3 200712 299901
  24. 5 5 200712 299901
  25. INSERT操作把I插入到HIS
  26. 用户标志 状态 开始时间 结束时间
  27. 1 1 200712 299901
  28. 2 2 200712 299901
  29. 3 3 200712 299901
  30. 4 4 200712 299901
  31. 5 5 200712 299901
  32. 1 2 200801 299901 –new
  33. 3 4 200801 299901 –new
  34. 5 6 200801 299901 –new
  35. </span>
  36. update操作按U更新HIS
  37. 用户标志 状态 开始时间 结束时间
  38. 1 1 200712 200801 –change
  39. 2 2 200712 299901
  40. 3 3 200712 200801 –change
  41. 4 4 200712 299901
  42. 5 5 200712 200801 –change
  43. 1 2 200801 299901
  44. 3 4 200801 299901
  45. 5 6 200801 299901

转载 :http://blog.csdn.NET/paopaomm/article/details/7491400

另一个操作SQL的例子

[sql] view plain copy

  1. 一个实际例子(teradata)
  2. 1、定义两个临时表,一个为当日全量数据,另一个为需要新增或更新的数据;
  3. CREATE VOLATILE TABLE VT_xxxx_NEW AS xxxx WITH NO DATA ON COMMIT PRESERVE ROWS;
  4. CREATE VOLATILE SET TABLE VT_xxxx_CHG,NO LOG AS xxxx WITH NO DATA ON COMMIT PRESERVE ROWS;
  5. 2、获取当日全量数据
  6. INSERT INTO VT_xxxx_NEW(xx) SELECT (xx,cur_date, max_date) FROM xxxx_sorce; ND
  7. 3、抽取新增或有变化的数据,从xxxx_NEW临时表到xxxx_CHG临时表;
  8. INSERT INTO VT_xxxx_CHG(xx)
  9. SELECT xx FROM VT_xxxx_NEW
  10. WHERE (xx) NOT IN (select xx from xxxx_HIS where end_date=‘max_date’);
  11. 4、更新历史表的失效记录的end_date为max
  12. UPDATE A1 FROM xxxx_HIS A1, VT_xxxx_CHG A2
  13. SET End_Date=‘current_date’
  14. WHERE A1.xx=A2.xx AND A1.End_Date=‘max_date’;
  15. 5、将新增或者有变化的数据插入目标表*/
  16. INSERT INTO xxxx_HIS SELECT * FROM VT_xxxx_CHG;

自己编写的例子:

[sql] view plain copy

  1. /**拉链表: 也就是一个 记录历史 表,用于记录事物从 最开始的状态 到 当前状态 所有变化的信息 */
  2. select * from emp ;
  3. –历史表
  4. DROP TABLE old_tb_his;
  5. drop table new_tb;
  6. create table old_tb_his(
  7. id number(10,0),
  8. status varchar2(20),
  9. start_date varchar2(20),
  10. end_date varchar2(20)
  11. );
  12. insert into old_tb_his values(1,‘1’, ‘200712’ , ‘299901’);
  13. insert into old_tb_his values(2,‘2’, ‘200712’ , ‘299901’);
  14. insert into old_tb_his values(3,‘3’, ‘200712’ , ‘299901’);
  15. insert into old_tb_his values(4,‘4’, ‘200712’ , ‘299901’);
  16. insert into old_tb_his values(5,‘5’, ‘200712’ , ‘299901’);
  17. –ROLLBACK;
  18. COMMIT;
  19. select * from old_tb_his;
  20. CREATE TABLE NEW_TB AS SELECT * FROM old_tb_his WHERE 2 =1 ;
  21. insert into NEW_TB values(1,‘2’, ‘200801’ , ‘299901’);
  22. insert into NEW_TB values(2,‘2’, ‘200801’ , ‘299901’);
  23. insert into NEW_TB values(3,‘4’, ‘200801’ , ‘299901’);
  24. insert into NEW_TB values(4,‘4’, ‘200801’ , ‘299901’);
  25. insert into NEW_TB values(5,‘6’, ‘200801’ , ‘299901’);
  26. COMMIT;
  27. SELECT * FROM NEW_TB;
  28. /*
  29. merge into old_tb_his
  30. using NEW_TB
  31. on (old_tb_his.id = NEW_TB.id and old_tb_his.status = new_tb.status )
  32. when matched then update set old_tb_his.end_date = NEW_TB.start_date
  33. when not matched then insert values(NEW_TB.id, NEW_TB.status, NEW_TB.start_date,NEW_TB.end_date);
  34. */
  35. /**用不了 这个函数是匹配就更新 不匹配添加
  36. 而拉链算法可以看作是 不匹配的更新 不匹配的也添加
  37. merge into old_tb_his
  38. using NEW_TB
  39. on (old_tb_his.id = NEW_TB.id and old_tb_his.status = new_tb.status )
  40. when not matched then update set old_tb_his.end_date = NEW_TB.start_date ;
  41. –when not matched then insert values(NEW_TB.id, NEW_TB.status, NEW_TB.start_date,NEW_TB.end_date);
  42. */
  43. –如果函数不能完成拉链算法 只能通过存储过程来完成
  44. select * from old_tb_his;
  45. SELECT * FROM NEW_TB;
  46. –创建临时表old_tb_his_temp
  47. CREATE GLOBAL TEMPORARY TABLE old_tb_his_temp
  48. (
  49. id number(10,0),
  50. status varchar2(20),
  51. start_date varchar2(20),
  52. end_date varchar2(20)
  53. )
  54. ON COMMIT DELETE ROWS ;
  55. –创建临时表new_tb_temp
  56. CREATE GLOBAL TEMPORARY TABLE new_tb_temp
  57. (
  58. id number(10,0),
  59. status varchar2(20),
  60. start_date varchar2(20),
  61. end_date varchar2(20)
  62. )
  63. ON COMMIT DELETE ROWS ;
  64. — W_I = ND – OD ( 将W_I表的内容全部插入到历史表中,这些是新增记录 )
  65. insert into old_tb_his_temp
  66. select *
  67. from new_tb t
  68. where t.id not in (select id
  69. from (select t1.id, t1.status, t1.end_date
  70. from old_tb_his t1
  71. intersect
  72. select t2.id, t2.status, t2.end_date
  73. from new_tb t2));
  74. — W_U = OD – ND ( 对历史表进行W_U部份的更新操作,start_date保持不变,而end_date改为当天 )
  75. insert into new_tb_temp
  76. select *
  77. from old_tb_his t
  78. where t.id not in (select id
  79. from (select t1.id, t1.status, t1.end_date
  80. from old_tb_his t1
  81. intersect
  82. select t2.id, t2.status, t2.end_date
  83. from new_tb t2));
  84. select * from old_tb_his_temp;
  85. select * from new_tb_temp;
  86. commit;
  87. –INSERT操作把I插入到HIS
  88. INSERT INTO old_tb_his
  89. SELECT * FROM old_tb_his_temp ;
  90. select * from old_tb_his ;
  91. –多表更新语句一: update 操作按U更新HIS
  92. merge into old_tb_his
  93. using old_tb_his_temp on (old_tb_his.id = old_tb_his_temp.id and old_tb_his.status <> old_tb_his_temp.status )
  94. when matched then update set old_tb_his.end_date = old_tb_his_temp.start_date ;
  95. –多表更新语句二: or: update 操作按U更新HIS
  96. update old_tb_his
  97. set old_tb_his.end_date = (select old_tb_his_temp.start_date from old_tb_his_temp where old_tb_his_temp.id = old_tb_his.id)
  98. where exists(
  99. select 1 from old_tb_his_temp where old_tb_his.id = old_tb_his_temp.id
  100. and old_tb_his.status <> old_tb_his_temp.status
  101. )
  102. commit;
  103. select * from old_tb_his
  104. select * from emp;
  105. –单表更新
  106. update emp set empno = 7777 where ename = upper(‘smith’) ;
  107. –多表更新
  108. merge into t2
  109. using t1 on (t2.id = t1.id and t2.status <> t1.status )
  110. when matched then update set t2.end_date = t1.start_date ;
  111. –or
  112. update t2
  113. set t2.end_date = (select t1.start_date from t1 where t1.id = t2.id)
  114. where exists(
  115. select 1 from t1 where t2.id = t1.id
  116. and t2.status <> t1.status
  117. )

转自: http://blog.csdn.net/badyflf/article/details/51097552

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/181234.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年10月16日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据保险箱
数据保险箱(Cloud Data Coffer Service,CDCS)为您提供更高安全系数的企业核心数据存储服务。您可以通过自定义过期天数的方法删除数据,避免误删带来的损害,还可以将数据跨地域存储,防止一些不可抗因素导致的数据丢失。数据保险箱支持通过控制台、API 等多样化方式快速简单接入,实现海量数据的存储管理。您可以使用数据保险箱对文件数据进行上传、下载,最终实现数据的安全存储和提取。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档