Sql 具有时间间隔的表行实例的快照
我不知道该怎么称呼这种现象。我刚刚将其命名为“具有时间间隔的表行实例快照”。我们需要创建一个新的实体,它是两个表的连接,但是这两个表有历史记录,我们需要合并到这个实体中。请看下面的示例: 在图中,您可以看到我们有两个表ABC和PQR,ID为键列。我们需要创建一个表ABCPQR,它将连接这两个表,并且这两个表的历史记录将包含来自各自表的两个属性的合并历史记录Sql 具有时间间隔的表行实例的快照,sql,analytics,teradata,data-warehouse,window-functions,Sql,Analytics,Teradata,Data Warehouse,Window Functions,我不知道该怎么称呼这种现象。我刚刚将其命名为“具有时间间隔的表行实例快照”。我们需要创建一个新的实体,它是两个表的连接,但是这两个表有历史记录,我们需要合并到这个实体中。请看下面的示例: 在图中,您可以看到我们有两个表ABC和PQR,ID为键列。我们需要创建一个表ABCPQR,它将连接这两个表,并且这两个表的历史记录将包含来自各自表的两个属性的合并历史记录 如何在数据库中实现这一点?我正在使用Teradata作为数据库,有什么算法可以实现这一点吗?没有复杂的算法。带交叉连接、介于和最大/最小函
如何在数据库中实现这一点?我正在使用Teradata作为数据库,有什么算法可以实现这一点吗?没有复杂的算法。带交叉连接、介于和最大/最小函数的简单sql即可
create table abc
( id integer,
attr1 varchar(3),
start_date date,
end_date date)
PRIMARY INDEX(ID);
create table PQR
( id integer,
attr2 varchar(3),
start_date date,
end_date date)
PRIMARY INDEX(ID);
INSERT INTO abc VALUES(1,'LMN','2017-01-01','2017-02-28');
INSERT INTO abc VALUES(1,'HGI','2017-02-28','2017-03-15');
INSERT INTO abc VALUES(1,'STI','2017-03-15','2099-12-31');
INSERT INTO PQR VALUES(1,'KLM','2017-01-01','2017-01-20');
INSERT INTO PQR VALUES(1,'TLF','2017-01-20','2017-04-04');
INSERT INTO PQR VALUES(1,'SNQ','2017-04-04','2099-12-31');
select a.id,a.attr1,p.attr2,
cast(greatest(cast(a.start_date as int),cast(p.start_date as int)) as date)start_date,
cast(least(cast(a.end_date as int),cast(p.end_date as int)) as date)end_date
from abc a
inner join pqr p
on a.id=p.id
where a.start_date between p.start_date and p.end_date
or a.end_date between p.start_date and p.end_date
order by 4;
输出:
id attr1 attr2 start_date end_date
1 1 LMN KLM 1/1/2017 1/20/2017
2 1 LMN TLF 1/20/2017 2/28/2017
3 1 HGI TLF 2/28/2017 3/15/2017
4 1 STI TLF 3/15/2017 4/4/2017
5 1 STI SNQ 4/4/2017 12/31/2099
唯一不同的是,我用2099而不是1999来简化这件事。您也可以使用1999并自定义此查询(但不是首选)。您可以使用Teradata的PERIOD数据类型快速完成此操作。句点是日期或时间戳的范围。它使用两个日期或时间戳作为参数,第一个用于开始日期,第二个用于结束日期(直到但不包括) 在您的情况下,我们将把您的
开始日期
和结束日期
转换为执行联接的时段。我们将使用特定于时段的函数P_INTERSECT
查找我们将加入的重叠时段
SELECT
attr1,
attr2,
/*pull the BEGIN of the intersected period*/
BEGIN(t1.validperiod P_INTERSECT t2.validperiod) as startdate,
/*pull the END of the intersected period (subtracting a day since period end
dates are "up to but not including")*/
PRIOR(END(t1.validperiod P_INTERSECT t2.validperiod)) as enddate
FROM
(SELECT abc.*, PERIOD(start_date, NEXT(end_date)) as validperiod FROM abc) t1
INNER JOIN (SELECT pqr.*, PERIOD(start_Date, NEXT(end_date)) as validperiod FROM pqr) t2 ON
t1.id = t2.id
/*
* Now P_INTERSECT our two periods and look for Non-Null intersections
* The intersection is the date range where the two periods overlap
*/
AND t1.validperiod P_INTERSECT t2.validperiod IS NOT NULL;
我们在这里获得了一些奖金:
t1.validperiod P_INTERSECT t2.validperiod P_INTERSECT t3.validperiod不为NULL
Simple最后,作为一项规则,当我创建表并且该表有开始日期和结束日期时,我总是创建一个名为validperiod的新字段,并像在这些子查询中一样加载它。然后,您不必转换为句点,您的加入就会变得友好。只需抓取已存储的validperiod列并开始P_相交。它消除了其他丑陋连接和选择的所有工作。感谢您的回答Bhavesh。嗨,JNevill。谢谢你的回答,但我想问一个简短的问题。你知道当我们连接多个表时P_INTERSECT是如何执行的吗?它非常快。我有一个p_与6或7个表相交,每个表有上万条记录,它在一分钟左右返回。这也是所有的左连接,所以我合并了每一个可能的交叉点。我意识到我在评论中说我是在结束(句点)-1,但忘了在SQL中实现它。我已将该字段的答案更新为:
previor(End(t1.validperiod P_INTERSECT t2.validperiod))
。此外,您可能会发现这篇关于Teradata的Period功能的老博文值得一看:这是一个很好的资源,有很多例子和解释。此外,我刚刚运行了我在第二条评论中提到的大型P_INTERSECT sql。它需要6个表,每个表有200k到600k条记录,它在单节点盒上2-3秒内将663746条记录输出到一个新表。