Как запрашивать и сортировать данные по их количеству, когда интервал времени между данными превышает 5 минут - PullRequest
0 голосов
/ 08 мая 2019

Я хочу запросить список данных его источника данных, как это:

ID       EVENT      TIME
--------------------------
A       EVENT_1     2019-05-07 18:26:39.000
B       EVENT_1     2019-05-07 18:31:39.000 
C       EVENT_3     2019-05-07 18:32:39.000
A       EVENT_2     2019-05-07 18:32:39.000
A       EVENT_2     2019-05-07 18:33:39.000
A       EVENT_1     2019-05-07 18:34:39.000
B       EVENT_2     2019-05-07 18:35:39.000
B       EVENT_1     2019-05-07 18:36:39.000
C       EVENT_2     2019-05-07 18:38:39.000
A       EVENT_1     2019-05-07 18:40:39.000
--------------------------

сначала выберите только самые ранние данные, когда данные с тем же идентификатором сработают снова через 5 минут (независимо от того, что это за событие)

Итак, данные должны выглядеть так:

ID       EVENT      TIME
--------------------------
A       EVENT_1     2019-05-07 18:26:39.000
B       EVENT_1     2019-05-07 18:31:39.000 
C       EVENT_3     2019-05-07 18:32:39.000
A       EVENT_2     2019-05-07 18:32:39.000
C       EVENT_2     2019-05-07 18:38:39.000
A       EVENT_1     2019-05-07 18:40:39.000
--------------------------

Спасибо, я использую SQL Server 2016

1 Ответ

0 голосов
/ 08 мая 2019

Не так просто, как кажется, рекурсивный CTE может включать в себя ближайшую запись по идентификатору 1: 1.

Настройка:

IF OBJECT_ID('tempdb..#EventData') IS NOT NULL
    DROP TABLE #EventData

CREATE TABLE #EventData (
    RowID INT IDENTITY,
    ID CHAR,
    Event VARCHAR(100),
    Time DATETIME)

INSERT INTO #EventData (
    ID,
    Event,
    Time)
VALUES
    ('A',' EVENT_1','2019-05-07 18:26:39.000'), 
    ('B',' EVENT_1','2019-05-07 18:31:39.000 '), 
    ('C',' EVENT_3','2019-05-07 18:32:39.000'), 
    ('A',' EVENT_2','2019-05-07 18:32:39.000'), 
    ('A',' EVENT_2','2019-05-07 18:33:39.000'), 
    ('A',' EVENT_1','2019-05-07 18:34:39.000'), 
    ('B',' EVENT_2','2019-05-07 18:35:39.000'), 
    ('B',' EVENT_1','2019-05-07 18:36:39.000'), 
    ('C',' EVENT_2','2019-05-07 18:38:39.000'), 
    ('A',' EVENT_1','2019-05-07 18:40:39.000')

Решение:

;WITH EarliestRecordByID AS
(
    SELECT
        E.ID,
        MinTime = MIN(E.Time)
    FROM
        #EventData AS E
    GROUP BY
        E.ID
),
EventDataWithClosestRecord AS
(
    SELECT
        E.RowID,
        E.ID,
        E.Event,
        E.Time,
        ClosestRowID = T.RowID
    FROM
        #EventData AS E
        OUTER APPLY (
            SELECT TOP 1
                C.RowID
            FROM
                #EventData AS C
            WHERE
                C.ID = E.ID AND
                C.Time > DATEADD(MINUTE, 5, E.Time)
            ORDER BY
                C.Time) AS T
),
RecursiveCTE AS
(
    SELECT
        E.ID,
        E.RowID,
        E.Event,
        E.Time,
        E.ClosestRowID
    FROM
        EventDataWithClosestRecord AS E
        INNER JOIN EarliestRecordByID AS M ON 
            E.ID = M.ID AND
            E.Time = M.MinTime

    UNION ALL

    SELECT
        R.ID,
        D.RowID,
        D.Event,
        D.Time,
        D.ClosestRowID
    FROM
        RecursiveCTE AS R
        INNER JOIN EventDataWithClosestRecord AS D ON R.ClosestRowID = D.RowID
)
SELECT
    R.ID,
    R.RowID,
    R.Event,
    R.Time
FROM
    RecursiveCTE AS R
ORDER BY
    R.Time
OPTION
    (MAXRECURSION 1000) -- Your max recursion level here (0 for unlimited)

Результат:

ID  RowID   Event       Time
A   1       EVENT_1     2019-05-07 18:26:39.000
B   2       EVENT_1     2019-05-07 18:31:39.000
C   3       EVENT_3     2019-05-07 18:32:39.000
A   4       EVENT_2     2019-05-07 18:32:39.000
C   9       EVENT_2     2019-05-07 18:38:39.000
A   10      EVENT_1     2019-05-07 18:40:39.000

Возможно, существует другое (возможно, более быстрое) решение с использованием оконных функций, поскольку рекурсивные решения в SQL Server имеют очень низкую производительность по сравнению с нерекурсивными.

...