Группировка логических событий - PullRequest
0 голосов
/ 06 ноября 2018

Моя таблица заполнена событиями из внешнего источника, такими как:

SELECT target_type, timer_type, event_happened_at
FROM tracked_events 
ORDER BY event_happened_at ASC;


TARGET_TYPE  TIMER_TYPE    EVENT_HAPPENED_AT
"JOB",       "START",      "2018-11-06 06:00:00+00"
"JOB",       "STOP",       "2018-11-06 10:30:00+00"
"PAUSE",     "START",      "2018-11-06 10:30:00+00"
"PAUSE",     "STOP",       "2018-11-06 11:00:00+00"
"JOB",       "START",      "2018-11-06 11:00:00+00"
"JOB",       "STOP",       "2018-11-06 15:00:00+00"

Мы можем видеть логическую группировку в три строки:

TYPE   START                   END
JOB,   2018-11-06 06:00:00+00, 2018-11-06 10:00:00+00
PAUSE, 2018-11-06 10:00:00+00, 2018-11-06 11:00:00+00
JOB,   2018-11-06 11:00:00+00, 2018-11-06 15:00:00+00

Я пытаюсь найти хороший способ выполнить эту группировку в SQL. Типы событий предопределены и гарантированно будут отправлены «логическим способом» (то есть PAUSE / START не произойдет до JOB / END., И начало / конец гарантированно будут существовать для всех событий.)

Так что, по сути, если я вижу JOB / START, мне нужно найти следующую JOB / END, и в равной степени для PAUSE / START to PAUSE / END.

Я вижу запрос, в котором я только ищу события START и выполняю подзапрос, чтобы найти соответствующий ему КОНЕЦ:

WITH starts AS (
    SELECT session_id, target_type, timer_type, event_happened_at
    FROM received_session_events 
    WHERE session_id = 266
    AND TIMER_TYPE = 'START'
    ORDER BY event_happened_at ASC
)

SELECT target_type, event_happened_at AS started_at,
       (
         SELECT event_happened_at 
         FROM received_session_events end_event
         WHERE session_id = starts.session_id 
         AND   timer_type = 'STOP' AND end_event.target_type = starts.target_type
         AND   end_event.event_happened_at > starts.event_happened_at
         ORDER BY event_happened_at ASC
         LIMIT 1
       ) AS ended_at
FROM starts

Это работает, дает правильный результат, но что-то кажется неэффективным и неуместным. Добавление индексов - это вариант, который я еще не исследовал (и при этом я не знаю, с чего начать, кроме очевидных, появляющихся в предложениях WHERE.)

1 Ответ

0 голосов
/ 06 ноября 2018

Предполагая, что данные соответствуют «логическому порядку» целей и времени события, рассмотрите возможность добавления номера строки и выполнения сдвинутого самостоятельного соединения:

WITH s2 AS
 (SELECT *, ROW_NUMBER() OVER() As ROW_NUM
  FROM received_session_events)         

SELECT CASE 
            WHEN s1.TARGET_TYPE = 'DEAL' 
            THEN 'JOB' 
            ELSE s1.TARGET_TYPE
       END AS "TYPE", s1.EVENT_HAPPENED_AT AS "START", s2.EVENT_HAPPENED_AT AS "END"
FROM s2 AS s1
JOIN 
   s2 
 ON s1.TARGET_TYPE = s2.TARGET_TYPE AND s1.ROW_NUM = s2.ROW_NUM - 1
ORDER BY s1.EVENT_HAPPENED_AT;

--   TYPE                    START                     END
--    JOB   2018-11-06 06:00:00+00  2018-11-06 10:30:00+00
--  PAUSE   2018-11-06 10:30:00+00  2018-11-06 11:00:00+00
--    JOB   2018-11-06 11:00:00+00  2018-11-06 15:00:00+00

Rextester Demo

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