HistoricalZipperTable是一种数据模型,主要是针对数据仓库设计中数据在表中的存储方式定义的;顾名思义,历史ZipperTable就是记录一笔交易从开始到当前状态的所有变化信息,ZipperTable可以避免每天存储所有记录带来的海量存储问题,它是也是处理缓慢变化数据的常用方法。1.概念在拉链表中,每条数据都有一个有效日期(sdate)和一个过期日期(edate)。假设在一个user表中,2019年10月8日新增了两个用户,这两条记录的生效时间就是那天,因为这两条记录直到2019年10月8日才被修改过,但是,所以过期时间是无限的,这里设置为数据库中的最大值(2999-12-31),如图:第二天(2019-10-09)删除用户1001,用户1002的电话号码为修改为16500000006,为了保留历史状态,将用户1001的过期时间修改为2019-10-09,用户1002变成两条记录,如图:第三天(2019-10-10),添加用户1003,用户表数据如图:如果要查询最新的数据,只需要查询过期时间为2999-12-31的数据即可;如果要查询10月8日的历史数据,过滤有效时间<=2019-10-08,过期时间>2019-10-08的数据即可;如果查询的是10月9日的数据,那么过滤条件是有效时间<=2019-10-09,过期时间>2019-10-09;等等。2.建表临时源表T_FIN_ACCTION_SRC接收其他数据库(如oracle)表推送的数据,表结构与源数据库一致。--源表createtableT_FIN_ACCTION_SRC(eNovarchar(6),eNamevarchar(10),ePhonevarchar(11),eData_datedate);目标表(即拉链表)T_FIN_ACCTION_TAR,这里注意是拉链表改变了源表的时间字段生效时间和过期时间。--zippertablecreatetableT_FIN_ACCTION_TAR(eNovarchar(6),eNamevarchar(10),ePhonevarchar(11),sdatedate,edatedate);3、存储过程的创建这里为了方便阅读和写代码,先写出整体的存储过程架构,然后我们一步步添加代码:--传入当前时间(也可以传入昨天的时间)时间,适应情况,如果传入的时间是今天,则需要将使用的时间减一,因为我们要处理的是昨天的数据)--传入当前时间(也可以传入昨天的时间,适应情况,如果传入的时间是今天,需要用的时间减一,因为我们要处理的是昨天的数据)createorreplacefunctionMy_FIN_GL_SUBJECT_PRO(INP_TODAYVARCHAR)returnsvoidas$$declarebegin--1。如果目标表中没有这个主键,则判断为new-add--2。如果源表中没有这个ID,则link-delete--3。修改--3.1闭链:目标表中有这条主键的记录,状态值不同,更新结束日期为同一天--3.2开链:新增一条修改数据目标表,更新结束日期为infinityend;$$languageplpgsql;4.zipper过程的实现1.如果目标表中没有这个主键,则判断为新增-addinsertintogplcydb.public.T_FIN_ACCTION_TAR(eNo,eName,ePhone,sdate,edate)selects.eNo,s。eName,s.ePhone,s.eData_date,to_date('2999-12-31','yyyy-mm-dd')fromgplcydb.public.T_FIN_ACCTION_SRCswheres.eData_date=(to_date(P_TODAY,'yyyy-mm-dd')-1)andnotexists(select1fromgplcydb.public.T_FIN_ACCTION_TARtwheres.eNo=t.eNoands.eName=t.eNameands.ePhone=t.ePhone);2.如果源表中没有这个ID,关闭链接——删除updategplcydb.public.T_FIN_ACCTION_TARasetedate=(to_date(P_TODAY,'yyyy-mm-dd')-1)wherenotexists(select1fromgplcydb.public.T_FIN_ACCTION_SRCswheres.eNo=a.eNoanda.edate=to_date('2999-12-31','yyyy-mm-dd'));3.修改3.1闭链:目标表中有这条主键的记录,状态值不同,更新结束日期为当天')-1)whereb.edate=to_date('2999-12-31','yyyy-mm-dd')andexists(select1fromgplcydb.public.T_FIN_ACCTION_SRCswheres.eNo=b.eNoandb.sdate<(to_date(P_TODAY,'yyyy-mm-dd')-1)and(s.eName<>b.eNameors.ePhone<>b.ePhone));3.2开链:在目标表中添加一条修改数据,更新结束日期为infinityinsertintogplcydb。public.T_FIN_ACCTION_TAR(eNo,eName,ePhone,sdate,edate)selects.eNo,s.eName,s.ePhone,(to_date(P_TODAY,'yyyy-mm-dd')-1),to_date('2999-12-31','yyyy-mm-dd')fromgplcydb.public.T_FIN_ACCTION_SRCswheres.eData_date=(to_date(P_TODAY,'yyyy-mm-dd')-1)andexists(--处理数据断开的新情况select1from(selecteNo,sdate,max(edate)end_datefromgplcydb.public.T_FIN_ACCTION_TARgroupbyeNo,sdate)twhereet.eNo=s.eNoands.eData_date=t.sdateandt.end_date<=to_date(P_TODAY,'yyyy-mm-dd'));5.测试测试拉链功能,首先要向原表插入数据(模拟一天全量数据):insertintoT_FIN_ACCTION_SRCvalues('1001','feiniu','18500000001','2019-10-10');insertintoT_FIN_ACCTION_SRCvalues('1002','beibei','18400000005','2019-10-10');insertintoT_FIN_ACCTION_SRCvalues('1003','yuyu'0,'1380,'2019-10-10');调用函数进行拉链测试:selectMy_FIN_GL_SUBJECT_PRO('2019-10-11');--调用函数select*fromT_FIN_ACCTION_TAR;--查询拉链表测试结果如下图:插入全量第二天的数据,这些数据中有新的数据,删除源数据,修改源数据。完整的模拟sql语句如下:deletefromT_FIN_ACCTION_SRCwhereeno='1003';insertintoT_FIN_ACCTION_SRCvalues('1004','kongkong','13800000666','2019-10-11');updateT_FIN_ACCTION_SRCsetename='xiaofeifei'whereeno='1001';*fromT_FIN_ACCTION_SRC;原表效果图如下:接下来执行压缩函数:--执行压缩函数selectMy_FIN_GL_SUBJECT_PRO('2019-10-12');select*fromT_FIN_ACCTION_TAR;--查询效果图目标表如下:。
