SQL Свернуть последовательные временные ряды вместе - PullRequest
2 голосов
/ 04 июня 2009

В 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 ]

3 голосов
/ 04 июня 2009

При условии отсутствия дублирования дубликатов, это должно сделать это:

;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

edit: изменено 2-е «TaskStartDate» на «TaskEndDate» при последнем выборе.

0 голосов
/ 04 июня 2009

В качестве альтернативы вы можете использовать это решение:

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

и ваш запрос будет тривиальным

0 голосов
/ 04 июня 2009

Это не красиво ... но вот какой-то 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...