Sql 寻找两条不同时间线的时间重叠
我正在使用SQL SERVER。我有两张桌子。表一和表二。它们都存储时间间隔,为了简单起见,只需说它们都有两个datetime2列,表1的列名是S1和S2,表2的列名是T1和T2,每一行S1都大于S2,正好是表2。我想计算S2和S1之间的间隔值(就像一个时间线),然后从S1和S2上T1和T2的重叠中减去它。我试过了,但不能超过计算的第一部分Sql 寻找两条不同时间线的时间重叠,sql,sql-server,tsql,Sql,Sql Server,Tsql,我正在使用SQL SERVER。我有两张桌子。表一和表二。它们都存储时间间隔,为了简单起见,只需说它们都有两个datetime2列,表1的列名是S1和S2,表2的列名是T1和T2,每一行S1都大于S2,正好是表2。我想计算S2和S1之间的间隔值(就像一个时间线),然后从S1和S2上T1和T2的重叠中减去它。我试过了,但不能超过计算的第一部分 DECLARE @x float SET x=0 SELECT SUM(S1-S2)-x from table1 (set x =(SELECT (T1-
DECLARE @x float
SET x=0
SELECT SUM(S1-S2)-x from table1
(set x =(SELECT (T1-T2) FROM table2
WHERE T1>=S1 and T2<=S2));
我想要的是找出S1和S2之间的总分钟数,除了与第二个表T1和T2间隔重叠的分钟数。当T1和T2之间的整个间隔在S1和S2之间时,我的查询用于第二个表中的第二行。
这有点复杂,希望这个例子能有所帮助
查询工作正常,但当T1或T2中的一个在S1和S2区间时,我无法计算与查询的重叠值。我应该运行多个查询吗?这里有什么相似之处 本例使用的是SQL Server 2008。 此解决方案假设表T中的所有间隔不相互重叠。 下面的文章详细解释了区间代数,我认为它们是一本非常好的读物。他们也有很好的图表 使用示例数据创建表 我用一种比原始问题更容易混淆的方式来命名这些专栏。我添加了几个不重叠的额外间隔,以说明建议的解决方案将它们过滤掉
DECLARE @TableS TABLE (ID int IDENTITY(1,1), DateFromS date, DateToS date);
DECLARE @TableT TABLE (ID int IDENTITY(1,1), DateFromT date, DateToT date);
INSERT INTO @TableS (DateFromS, DateToS) VALUES ('2012-10-25', '2012-11-30');
INSERT INTO @TableS (DateFromS, DateToS) VALUES ('2015-10-25', '2015-11-30');
INSERT INTO @TableT (DateFromT, DateToT) VALUES ('2012-10-20', '2012-10-28');
INSERT INTO @TableT (DateFromT, DateToT) VALUES ('2012-11-04', '2012-11-08');
INSERT INTO @TableT (DateFromT, DateToT) VALUES ('2012-11-22', '2012-11-30');
INSERT INTO @TableT (DateFromT, DateToT) VALUES ('2010-11-22', '2010-11-30');
INSERT INTO @TableT (DateFromT, DateToT) VALUES ('2020-11-22', '2020-11-30');
寻找重叠的间隔
我假设我们要对表S中的每一行和表T中的每一行进行这些计算。如果不是这样,您应该使用一些额外的条件连接表
在本例中,我只使用天的精度,而不是分钟,并且我假设开始日期和结束日期都包含在内,即2000年1月1日到2000年1月1日之间的持续时间为一天。将其扩展到分钟精度应该相当简单
SELECT *
,ISNULL(1+DATEDIFF(day, MaxDateFrom.DateFrom, MinDateTo.DateTo), 0) AS OverlappedDays
FROM
@TableS AS TS
LEFT JOIN @TableT AS TT ON TS.DateFromS <= TT.DateToT AND TS.DateToS >= TT.DateFromT
-- all periods in TS, which overlap with periods in TT
--(StartA <= EndB) and (EndA >= StartB)
CROSS APPLY
(
SELECT CASE WHEN TS.DateFromS > TT.DateFromT THEN TS.DateFromS ELSE TT.DateFromT END AS DateFrom
) AS MaxDateFrom
CROSS APPLY
(
SELECT CASE WHEN TS.DateToS < TT.DateToT THEN TS.DateToS ELSE TT.DateToT END AS DateTo
) AS MinDateTo
注意,最后一行对应于表S中的间隔与表t中的任何间隔不重叠的情况
计算持续时间
现在我们只需要求出表S中每个原始行的重叠区间T的持续时间,然后从区间S的持续时间中减去它
SELECT
TS.ID
,TS.DateFromS
,TS.DateToS
,1+DATEDIFF(day, TS.DateFromS, TS.DateToS) AS DurationS
,ISNULL(SUM(1+DATEDIFF(day, MaxDateFrom.DateFrom, MinDateTo.DateTo)), 0) AS DurationOverlapped
,1+DATEDIFF(day, TS.DateFromS, TS.DateToS)
- ISNULL(SUM(1+DATEDIFF(day, MaxDateFrom.DateFrom, MinDateTo.DateTo)), 0) AS FinalDuration
FROM
@TableS AS TS
LEFT JOIN @TableT AS TT ON TS.DateFromS <= TT.DateToT AND TS.DateToS >= TT.DateFromT
CROSS APPLY
(
SELECT CASE WHEN TS.DateFromS > TT.DateFromT THEN TS.DateFromS ELSE TT.DateFromT END AS DateFrom
) AS MaxDateFrom
CROSS APPLY
(
SELECT CASE WHEN TS.DateToS < TT.DateToT THEN TS.DateToS ELSE TT.DateToT END AS DateTo
) AS MinDateTo
GROUP BY TS.ID, TS.DateFromS, TS.DateToS
您对FinalDuration
值感兴趣,对于您的示例,该值为19,对于我为本示例添加的第二个时间间隔,该值为37。
您可以向示例数据中添加更多的时间间隔来处理查询,并查看它们是如何工作的
此解决方案假设表T中的所有间隔不相互重叠。能否添加一个示例?阅读你的问题时我感到困惑。你希望从上面的例子中得到什么?
ID DateFromS DateToS ID DateFromT DateToT DateFrom DateTo OverlappedDays
1 2012-10-25 2012-11-30 1 2012-10-20 2012-10-28 2012-10-25 2012-10-28 4
1 2012-10-25 2012-11-30 2 2012-11-04 2012-11-08 2012-11-04 2012-11-08 5
1 2012-10-25 2012-11-30 3 2012-11-22 2012-11-30 2012-11-22 2012-11-30 9
2 2015-10-25 2015-11-30 NULL NULL NULL NULL NULL 0
SELECT
TS.ID
,TS.DateFromS
,TS.DateToS
,1+DATEDIFF(day, TS.DateFromS, TS.DateToS) AS DurationS
,ISNULL(SUM(1+DATEDIFF(day, MaxDateFrom.DateFrom, MinDateTo.DateTo)), 0) AS DurationOverlapped
,1+DATEDIFF(day, TS.DateFromS, TS.DateToS)
- ISNULL(SUM(1+DATEDIFF(day, MaxDateFrom.DateFrom, MinDateTo.DateTo)), 0) AS FinalDuration
FROM
@TableS AS TS
LEFT JOIN @TableT AS TT ON TS.DateFromS <= TT.DateToT AND TS.DateToS >= TT.DateFromT
CROSS APPLY
(
SELECT CASE WHEN TS.DateFromS > TT.DateFromT THEN TS.DateFromS ELSE TT.DateFromT END AS DateFrom
) AS MaxDateFrom
CROSS APPLY
(
SELECT CASE WHEN TS.DateToS < TT.DateToT THEN TS.DateToS ELSE TT.DateToT END AS DateTo
) AS MinDateTo
GROUP BY TS.ID, TS.DateFromS, TS.DateToS
ID DateFromS DateToS DurationS DurationOverlapped FinalDuration
1 2012-10-25 2012-11-30 37 18 19
2 2015-10-25 2015-11-30 37 0 37