SQL Server:如何将一系列连续的开始和结束日期时间转换为单个开始 - 结束范围?

时间:2013-11-25 15:52:19

标签: sql sql-server

在SQL Server中,我有一个停机时间列表。它列出了每个停机时间的起始值和结束值。我想得到最后的约会,但每一个都是约会的日期。

示例:

我们假设每个停机时间都在同一天。

A)  begin 09:00 End 11:00
B)  begin 10:00 End 12:00
C)  begin 12:00 End 13:00
D)  begin 15:00 End 16:00

测试用例:

1) 
At - 11:00  
Results: Begin A (9:00), End C (13:00)

2) 
At - 11:30  
Results: Begin B (10:00), End C (13:00)

3) 
At - 12:00  
Results: Begin B (10:00), End C (13:00)

4) 
At - 12:30  
Results: Begin C (10:00), End C (13:00)

如果我们只查看“结束”值。它始终是最后的日期,每个日期混合在一起。它就像把时间停留在一个时间线上一样。你把它放在检查停机时间。无论是停机时间A还是B或C ....

注意:只有SQL查询,没有功能。我更喜欢没有递归但是。


来自麦克答案:

DECLARE @Downtime AS TABLE(beginDT datetime, endDT datetime)
INSERT INTO @Downtime VALUES('09:00','11:00')
INSERT INTO @Downtime VALUES('10:00','12:00')
INSERT INTO @Downtime VALUES('12:00','13:00')
INSERT INTO @Downtime VALUES('15:00','16:00')

我想我需要递归。 搜索@DateNow需要在beginDT和endDT之间。如果每个的endDT都有另一个停机时间,我们需要递归检查。

在我的样本中,A-B-C是连续的(或同时)。所以,如果currentTime在A的乞讨和C的结尾之间,那么实际结束时间是树停机时间的结束(13:00)

9    10   11   12     13     14      15     16

|----A----|

     |----B----|

               |---C---|

                                      |---D---|


|---- A and B and C ---|

1 个答案:

答案 0 :(得分:0)

好的,基于扩展数据,您(可能)需要递归:

- 测试变量&环境

DECLARE @TimeParam AS DATETIME
DECLARE @Downtime AS TABLE(ID VARCHAR(1), beginDT datetime, endDT datetime)
INSERT INTO @Downtime VALUES('a','09:00','11:00')
INSERT INTO @Downtime VALUES('b','10:00','12:00')
INSERT INTO @Downtime VALUES('c','12:00','13:00')
INSERT INTO @Downtime VALUES('d','15:00','16:00')
INSERT INTO @Downtime VALUES('e','12:00','17:00') 
INSERT INTO @Downtime VALUES('f','15:00','19:00') 
INSERT INTO @Downtime VALUES('g','19:00','20:00') 
INSERT INTO @Downtime VALUES('h','20:00','21:00') 
INSERT INTO @Downtime VALUES('i','21:00','22:00') 
INSERT INTO @Downtime VALUES('j','22:00','23:00')

SET @TimeParam ='1900-01-01 15:30:00.000'

- 查询

DECLARE @Depth as INT --(Use this to control the recursion)
SET @Depth = 4
;WITH ConsecutiveDownTimeBase (ID, beginDT, endDT,IsBase)
AS 
(
SELECT ID
    , beginDT
    , endDT
    , 1 IsBase
FROM @DownTime dt
WHERE @TimeParam BETWEEN beginDT AND endDT
UNION ALL
-- Recursive member definition
SELECT a.ID
    , a.beginDT
    , a.endDT
    , b.IsBase+1
FROM ConsecutiveDownTimeBase AS b
INNER JOIN @Downtime a
    ON b.endDT BETWEEN a.beginDT and a.endDT
    AND b.IsBase<=@Depth
UNION ALL
-- Recursive member definition
SELECT c.ID
    , c.beginDT
    , c.endDT
    , b.IsBase+1
FROM ConsecutiveDownTimeBase AS b
INNER JOIN @Downtime c
    ON b.beginDT BETWEEN c.beginDT and c.endDT
    AND b.IsBase<=@Depth
)
SELECT CONVERT(TIME,MIN(beginDT)) AS beginDT
     , CONVERT(TIME,MAX(endDT))   AS endDT 
FROM ConsecutiveDownTimeBase

结果如下:

beginDT             endDT
09:00:00.0000000    23:00:00.0000000