拉链表

  1 /*拉链表: 也就是一个 记录历史 表,用于记录事物从 最开始的状态 到 当前状态 所有变化的信息 */
  2 
  3 --历史表
  4 drop table old_tb_his;
  5 drop table new_tb;
  6 
  7 
  8 --od 我们希望的拉链表记录数据的所有状态,初始化为昨日全量数据
  9 create table old_tb_his(
 10 id  number(10,0),
 11 status  varchar2(20),
 12 start_date varchar2(20),
 13 end_date varchar2(20)
 14 );
 15 insert into old_tb_his values(1,'1', '200712' , '299901');
 16 insert into old_tb_his values(2,'2', '200712' , '299901');
 17 insert into old_tb_his values(3,'3', '200712' , '299901');
 18 insert into old_tb_his values(4,'4', '200712' , '299901');
 19 insert into old_tb_his values(5,'5', '200712' , '299901');
 20 commit;
 21 select * from old_tb_his;
 22 
 23 
 24 --nd 今日全量数据
 25 create table new_tb as select * from old_tb_his where 2 = 1 ;
 26 insert into new_tb values(1,'2', '200801' , '299901');
 27 insert into new_tb values(2,'2', '200801' , '299901');
 28 insert into new_tb values(3,'4', '200801' , '299901');
 29 insert into new_tb values(4,'4', '200801' , '299901');
 30 insert into new_tb values(5,'6', '200801' , '299901');
 31 commit;
 32 select * from new_tb;
 33 
 34 
 35 /*merge into old_tb_his
 36  using new_tb
 37  on (old_tb_his.id = new_tb.id and old_tb_his.status = new_tb.status )
 38 when matched then  update set old_tb_his.end_date =  new_tb.start_date
 39 when not matched then insert values(new_tb.id, new_tb.status, new_tb.start_date,new_tb.end_date);*/
 40 
 41 
 42 /*
 43 用不了  这个函数是匹配就更新   不匹配添加
 44    而拉链算法可以看作是 不匹配的更新 不匹配的也添加
 45 */
 46 /*merge into old_tb_his
 47  using new_tb
 48  on (old_tb_his.id = new_tb.id and old_tb_his.status = new_tb.status )
 49 when not matched then update set old_tb_his.end_date =  new_tb.start_date ;
 50 when not matched then insert values(new_tb.id, new_tb.status, new_tb.start_date,new_tb.end_date);
 51 */
 52 --如果函数不能完成拉链算法 只能通过存储过程来完成
 53 select * from old_tb_his;
 54 select * from new_tb;
 55 
 56 
 57 drop table old_tb_his_temp;
 58 drop table new_tb_temp;
 59 --创建临时表old_tb_his_temp
 60 create global temporary  table old_tb_his_temp
 61 (
 62 id  number(10,0),
 63 status  varchar2(20),
 64 start_date varchar2(20),
 65 end_date varchar2(20)
 66 )
 67 on commit delete rows ;
 68 
 69 --创建临时表new_tb_temp
 70 create global temporary  table new_tb_temp
 71 (
 72 id  number(10,0),
 73 status  varchar2(20),
 74 start_date varchar2(20),
 75 end_date varchar2(20)
 76 )
 77 on commit delete rows ;
 78 
 79 
 80 -- w_i = nd - od  (  将w_i表的内容全部插入到历史表中,这些是新增记录 )
 81 --今日全量数据减去拉链表数据 等于新增数据 用w_i表示
 82 --UNION(无重并集)、UNION ALL(有重并集)、INTERSECT(交集)、MINUS (差集):只显示在第一个集合中存在,在第二个集合中不存在的数据
 83 insert into old_tb_his_temp
 84   select *
 85     from new_tb t
 86    where t.id not in (select id--今日全量数据,减去拉链表数据和今日全量数据的交集,等于今日新增数据
 87                         from (select t1.id, t1.status, t1.end_date
 88                                 from old_tb_his t1
 89                               intersect
 90                               select t2.id, t2.status, t2.end_date
 91                                 from new_tb t2));--查询拉链表数据和今日全量数据的交集
 92 
 93 -- w_u = od - nd ( 对历史表进行w_u部份的更新操作,start_date保持不变,而end_date改为当天 )封链
 94 insert into new_tb_temp
 95 select *
 96   from old_tb_his t
 97  where t.id not in (select id--拉链表数据,减去拉链表数据和今日全量数据的交集,等于待更新数据
 98                       from (select t1.id, t1.status, t1.end_date
 99                               from old_tb_his t1
100                             intersect
101                             select t2.id, t2.status, t2.end_date
102                               from new_tb t2));--查询拉链表数据和今日全量数据的交集
103 --查询两个临时表
104 select * from old_tb_his_temp;
105 select * from new_tb_temp;
106 commit;
107 
108 --insert操作把w_i插入到拉链表
109 insert into old_tb_his
110 select * from old_tb_his_temp ;
111 --查询是否成功插入
112 --select * from old_tb_his ;
113 
114 
115 --多表更新语句一: update 操作按u更新his
116 /*merge into old_tb_his
117 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 )
118  when matched then update set old_tb_his.end_date = old_tb_his_temp.start_date ;*/
119 
120 --多表更新语句二: or: update 操作按u更新his
121 update old_tb_his
122 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)
123 where exists(
124 select 1 from old_tb_his_temp where old_tb_his.id = old_tb_his_temp.id
125                                 and old_tb_his.status <> old_tb_his_temp.status
126 );
127 
128 commit;
129 
130 
131 select * from old_tb_his
132 
133 用户标志       状态 开始时间 结束时间
134 1               1   200712  200801 --change
135 2               2   200712  299901
136 3               3   200712  200801 --change
137 4               4   200712  299901
138 5               5   200712  200801 --change
139 1               2   200801  299901
140 3               4   200801  299901
141 5               6   200801  299901

 

posted @ 2017-11-10 10:46  阳光下的me  阅读(1860)  评论(0编辑  收藏  举报