SQL折叠顺序时间系列设置在一起

时间:2009-06-04 07:21:32

标签: sql-server tsql

在MSSQL中,我有一组具有开始和结束时间的任务。

我希望做的是将顺序任务折叠在一起 所以我对顺序的定义是TaskEndDate等于下一个TaskStartDate的开始,没有时间间隔。

在下面的数据集中,21:00到21:40是一个序列,然后是22:00到22:20& 23:20到00:00。

TaskStartDate             TaskEndDate
2008-09-01 21:00:00.000 2008-09-01 21:05:00.000
2008-09-01 21:05:00.000 2008-09-01 21:10:00.000
2008-09-01 21:10:00.000 2008-09-01 21:15:00.000
2008-09-01 21:15:00.000 2008-09-01 21:20:00.000
2008-09-01 21:20:00.000 2008-09-01 21:25:00.000
2008-09-01 21:25:00.000 2008-09-01 21:30:00.000
2008-09-01 21:30:00.000 2008-09-01 21:35:00.000
2008-09-01 21:35:00.000 2008-09-01 21:40:00.000
2008-09-01 22:00:00.000 2008-09-01 22:05:00.000
2008-09-01 22:05:00.000 2008-09-01 22:10:00.000
2008-09-01 22:10:00.000 2008-09-01 22:15:00.000
2008-09-01 22:15:00.000 2008-09-01 22:20:00.000
2008-09-01 23:20:00.000 2008-09-01 23:25:00.000
2008-09-01 23:25:00.000 2008-09-01 23:30:00.000
2008-09-01 23:30:00.000 2008-09-01 23:35:00.000
2008-09-01 23:35:00.000 2008-09-01 23:40:00.000
2008-09-01 23:40:00.000 2008-09-01 23:45:00.000
2008-09-01 23:45:00.000 2008-09-01 23:50:00.000
2008-09-01 23:50:00.000 2008-09-01 23:55:00.000
2008-09-01 23:55:00.000 2008-09-02 00:00:00.000

随意使用CTE或其他MSSQL特定功能。

3 个答案:

答案 0 :(得分:3)

假设没有重复的重叠,这应该这样做:

;WITH cteStart As (
    SELECT TaskStartDate,
        ROW_NUMBER() OVER(ORDER BY TaskStartDate) as N
    FROM YourTable y
    WHERE TaskStartDate NOT IN(SELECT TaskEndDate FROM YourTable y1)
), cteEnd As (
    SELECT TaskEndDate,
        ROW_NUMBER() OVER(ORDER BY TaskEndDate) as N
    FROM YourTable y
    WHERE TaskEndDate NOT IN(SELECT TaskStartDate FROM YourTable y1)
)
SELECT TaskStartDate, TaskEndDate
FROM cteStart as s
    JOIN cteEnd as e ON e.N = s.N

编辑:在最后一次选择时将第二个“TaskStartDate”更改为“TaskEndDate”。

答案 1 :(得分:0)

它不是很好......但这里有一些似乎有用的SQL。只需将[任务]替换为您的表名。

SET NOCOUNT ON

DECLARE @date DATETIME
DECLARE @continueLoop INT
DECLARE @continueInnerLoop INT

DECLARE @tmp TABLE (
    [Start] [DateTime] NOT NULL , 
    [End] [DateTime] NOT NULL
)

SET @continueLoop = 1

WHILE @continueLoop <> 0 BEGIN
    INSERT INTO @tmp
    SELECT TOP 1 [TaskStartDate], [TaskEndDate]
    FROM [dbo].[Tasks]
    WHERE [TaskStartDate] > ISNULL((SELECT TOP 1 [End] FROM @tmp ORDER BY [End] DESC), '19000101')
    SET @continueInnerLoop = @@ROWCOUNT

    WHILE @continueInnerLoop <> 0 BEGIN
        UPDATE @tmp
        SET [End] = Tasks.[TaskEndDate]
        FROM @tmp, [dbo].[Tasks] 
        WHERE [End] = Tasks.[TaskStartDate]
    SET @continueInnerLoop = @@ROWCOUNT
    END

    SELECT @continueLoop = COUNT(*)
    FROM [dbo].[Tasks]
    WHERE [TaskStartDate] > ISNULL((SELECT TOP 1 [End] FROM @tmp ORDER BY [End] DESC), '19000101')
END

SELECT * FROM @tmp

结果产生以下结果

[TaskStartDate], [TaskEndDate]
2008-09-01 21:00:00.000, 2008-09-01 21:40:00.000
2008-09-01 22:00:00.000, 2008-09-01 22:20:00.000
2008-09-01 23:20:00.000, 2008-09-02 00:00:00.000

答案 2 :(得分:0)

或者您可以使用此解决方案:

http://sqlblog.com/blogs/alexander_kuznetsov/archive/2009/03/08/storing-intervals-of-time-with-no-overlaps.aspx

,您的查询将是微不足道的