计算重叠时间范围内的分钟总和

时间:2016-08-03 15:51:04

标签: sql sql-server tsql

我需要计算术语的总分钟数。重叠的术语不应多次计算。

Declare @Terms table (Start DATETIME, Finish DATETIME)
INSERT INTO @Terms values
    ('2016-8-3 08:00','2016-8-3 09:00'),
    ('2016-8-3 09:00','2016-8-3 10:00'),
    ('2016-8-3 08:00','2016-8-3 09:30'),   -- overlapping term
    ('2016-8-3 11:00','2016-8-3 12:00')

上述数据的结果应为180分钟(3小时)。什么是最简单,最快捷的方法?

3 个答案:

答案 0 :(得分:4)

借助交叉申请。

Declare @Terms table (Start DATETIME, Finish DATETIME)
INSERT INTO @Terms values
    ('2016-8-3 08:00','2016-8-3 09:00'),
    ('2016-8-3 09:00','2016-8-3 10:00'),
    ('2016-8-3 08:00','2016-8-3 09:30'),   -- overlapping term
    ('2016-8-3 11:00','2016-8-3 12:00')

Select Minutes = sum(Minutes)
 From (
        Select Distinct 
               B.DateR1
              ,B.DateR2
              ,Minutes = DateDiff(Minute,B.DateR1,B.DateR2)
         From @Terms A
         Cross Apply (
                      Select DateR1=Min(Start)
                            ,DateR2=max(Finish) 
                       From  @Terms 
                       Where Start <= A.Finish and Finish >= A.Start
                     ) B
 ) A

返回

Minutes
180

子查询返回

DateR1                     DateR2                   Minutes
2016-08-03 08:00:00.000    2016-08-03 10:00:00.000  120
2016-08-03 11:00:00.000    2016-08-03 12:00:00.000  60

答案 1 :(得分:0)

您可以执行LEAD函数,该函数属于窗口语句,以查找重叠。我创建了一个名为TIME_TEST的表并插入了您的值,当我总结差异时,它会返回三个小时。Lead Function Documentation

SELECT SUM(PREV_TIME - END_TIME) FROM (
SELECT *, LEAD(END_TIME) OVER(ORDER BY START_TIME) PREV_TIME
FROM TIME_TEST
ORDER BY 1
)FOO
;

答案 2 :(得分:0)

DECLARE @MAX as datetime;

SELECT @MAX = MAX(finish) FROM TERMS;

;WITH MINS AS (SELECT MIN(Start) N FROM TERMS
                UNION ALL
                SELECT dateadd(mi, 1, N) FROM MINS WHERE N < @MAX),
      OVERLAPMINS AS (
                        SELECT Mins.N from MINS 
                                            JOIN Terms T 
                                                    ON   T.Start <= MINS.N AND MINS.N < T.Finish 
                                                        GROUP BY Mins.N 
                                                            HAVING COUNT(0) > 1
                        )
      SELECT COUNT(0) totalmins FROM OVERLAPMINS 
option(maxrecursion 0)

除了我得到90,如果重叠的术语不计算多次,你如何使它3小时?你似乎已经计算了两次重叠。如果第三个时间段在不同时间与1个和2个其他时期重叠,该怎么办?你是说重叠的时期总是被计算两次(这是好的,因为任何重叠都有> = 2个时期在任何一分钟重叠)所以你可以将我的数量乘以2

...SELECT 2 * COUNT(0) totalmins..

如果您想将重叠计为2,但不能再计算