Запрос суммирования последующих длительностей, которые не выполняются одновременно - PullRequest
0 голосов
/ 17 мая 2019

У меня есть запрос, который извлекает время начала и окончания задержки для события и вычисляет длину в CTE.Может быть несколько задержек, связанных с одним событием, но из-за задержек пользовательских ошибок может происходить одновременно.Я хочу написать запрос, который суммирует все последовательные задержки вместе, включая одну длительность для любого, который выполняется одновременно, как рассчитано по задержке, которая началась раньше.

Чтобы получить таблицу данных: USE [tempdb]

GO

CREATE TABLE [dbo].[tblDelay](
        [Delay_ID] [INT] NOT NULL,
        [EventID] [INT] NOT NULL,
        [D_Time] [Datetime] NOT NULL,
        [D_EndTime] [Datetime]
        )
GO

INSERT INTO tblDelay VALUES(1,1,'10:00','10:01');
INSERT INTO tblDelay VALUES(2,1,'10:05','10:06');
INSERT INTO tblDelay VALUES(3,1,'10:05:01','10:06');
INSERT INTO tblDelay VALUES(4,2,'10:00','10:01');
INSERT INTO tblDelay VALUES(5,2,'10:04','10:05');
INSERT INTO tblDelay VALUES(6,2,'10:06','10:07');
INSERT INTO tblDelay VALUES(7,2,'10:06:01','10:07');
INSERT INTO tblDelay VALUES(8,2,'10:10','10:12');
INSERT INTO tblDelay VALUES(8,2,'10:10:01','10:12');

Я попытался сделать это, используя ЛЕВОЕ СОЕДИНЕНИЕ, чтобы выбрать немедленную следующую задержку, а затем подвести итоги.Я могу сделать несколько самостоятельных объединений, но я хочу, чтобы оно масштабировалось автоматически, а не только для проверки на установленное количество задержек.Код ниже работает:

WITH DelLength AS
(
    SELECT 
        EventID, Delay_ID,
        D_time, d_EndTime,
        CAST(CAST(DATEDIFF(SECOND, D_Time, D_EndTime) AS DECIMAL(10, 2)) / 60 AS DECIMAL(10, 2)) AS DelLength
    FROM 
        tblDelay d
)
SELECT
    dl1.EventID,
    dl1.D_Time,
    dl1.D_EndTime,
    (dl1.DelLength + dl2.DelLength + dl4.DelLength) AS Total
FROM
    DelLength AS dl1
INNER JOIN 
    tblEvent e ON dl1.EventID = e.EventID
LEFT JOIN 
    DelLength AS dl2 ON dl1.EventID = dl2.EventID
                     AND dl2.D_Time = (SELECT TOP 1 dl3.D_Time
                                       FROM DelLength dl3
                                       WHERE dl3.EventID = dl1.EventID
                                         AND dl3.D_Time > dl1.D_EndTime
                                       ORDER BY dl3.D_Time)
LEFT JOIN 
    DelLength dl4 ON dl4.EventID = dl1.EventID
                  AND dl4.D_Time = (SELECT TOP 1 dl5.D_Time
                                    FROM DelLength as dl5
                                    WHERE dl5.EventID = dl1.EventID
                                      AND dl5.D_Time > dl2.D_EndTime
                                    ORDER BY dl5.D_Time)

Создает запись для каждого события и сумму первой, второй и третьей последующих задержек, как описано (если присутствует).Но я хочу, чтобы код и неопределенное количество последующих задержек.

Заранее спасибо!

Ответы [ 2 ]

1 голос
/ 17 мая 2019

Вы ищете решение для виртуализации групп островов в упорядоченном порядке по времени. Может помочь что-то похожее на запрос ниже. Виртуализируйте группу и возьмите минимальное и максимальное значения для каждой группы, отдельные записи или не островные записи будут упорядочены последовательно по мере их падения, в то время как все записи в пределах острова будут иметь тот же последовательный порядок, что и первая запись в группе.

;WITH Markers AS
(
    SELECT
        *,
        VirtualGroupID = SUM(IsNewGroup) OVER (ORDER BY D_Time ROWS UNBOUNDED PRECEDING)
    FROM
    (        
        SELECT
            EventID, Delay_ID,
            D_time, d_EndTime,
            IsNewGroup = CASE WHEN ISNULL(LAG(EventID) OVER (ORDER BY D_Time),EventID)<>EventID THEN 1 ELSE 0 END
        FROM
            tblDelay d
    )AS X
)

SELECT 
    EventID = MAX(EventId),
    d_Time = MIN(d_Time),
    d_EndTime = MAX(d_EndTime)
FROM 
    Markers
GROUP BY
    VirtualGroupID
0 голосов
/ 18 мая 2019

Большое спасибо за то, что поставили меня на правильный путь, Росс. Я обнаружил, что ваш ответ был на 90% пути к тому, что я искал, его просто нужно было дополнить уточнением выражения окна в самом внутреннем подзапросе. Чтобы предотвратить задержку, начавшуюся до окончания последней, я расширил код:

WITH Markers AS
(
    SELECT
        *,
        VirtualGroupID = SUM(IsNewGroup) OVER (ORDER BY D_Time ROWS UNBOUNDED PRECEDING)
    FROM
    (        
        SELECT
            EventID, Delay_ID,
            D_time, d_EndTime,
            IsNewGroup = CASE 
                        WHEN        
ISNULL(LAG(EventID) OVER (ORDER BY EventID, D_Time),EventID)<>EventID 
                        OR          
(LAG(EventID) OVER (ORDER BY EventID, D_Time) = EventID 
AND D_Time > LAG(D_EndTime) OVER (ORDER BY EventID,D_Time)) 
                        THEN 1 
                        ELSE 0 END
        FROM
            tblDelay d
    )AS X

)

SELECT 
    EventID = MAX(EventId),
    d_Time = MIN(d_Time),
    d_EndTime = MAX(d_EndTime)
FROM 
    Markers

GROUP BY
    VirtualGroupID
    ORDER BY EventID

Я думаю, что это правильно.

Еще раз спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...