Хотя цикл для Teradata

Мир.

Я пытаюсь найти способ собрать несколько событий вместе. Данные выглядят так:

Существующие данные

По сути, это ряд данных строк с журналами событий.

Я хочу сгенерировать агрегацию этих событий строки так, чтобы, если новое событие произошло в течение 30 секунд после другого окончания, оно объединяло время вместе. Однако, если в журнале событий нет сопутствующего события, он не фиксируется. И эти события специфичны для человека.

Я предполагаю, что вывод будет выглядеть примерно так:

Выходные данные

Моя интуиция предлагает использовать какой-то цикл while, но я не уверен, с чего начать

Всего 2 ответа


Там нет необходимости для рекурсии (и очень трудно писать) или цикла над курсором.

SELECT
   Person,
   Min(starttime),
   Max(starttime),
   -- get a concatenated string
   Trim(Trailing ',' FROM (XmlAgg(Reason || ',' ORDER BY Reason ) (VARCHAR(1000))))
FROM
 (
   SELECT Person, Start_timestamp, Stop_timestamp, Reason,
     -- assign the same number to all rows within 30 seconds 
     Sum(flag) Over
     Over (PARTITION BY Person
           ORDER BY Start_timestamp
           ROWS Unbounded Preceding) AS grp
   FROM
    (
      SELECT Person, Start_timestamp, Stop_timestamp, Reason,
         -- check if previous end is within 30 seconds of the current start
         CASE WHEN Lag(Stop_timestamp) 
                   Over (PARTITION BY Person
                         ORDER BY Start_timestamp) + INTERVAL ཚ' SECOND < Start_timestamp
              THEN 0
              ELSE 1
         END AS flag
      FROM tab
    ) AS dt
 ) AS dt
-- aggregate per person and group
GROUP BY Person, grp

Если ваша версия Teradata поддерживает SESSIONIZE вы можете упростить вычисление группы, но я не смог написать этот синтаксис ad hoc :-)


Вы можете добиться этого с помощью RECURSIVE CTE

WITH RECURSIVE MYREC(Person,Start_timestamp,Stop_timestamp ,Reason,LVL)
 AS(
 SELECT Person,MIN(Start_timestamp),MAX(Stop_timestamp),MIN(Reason)(varchar(100)) AS Reason,1
 FROM MYTABLE
 GROUP BY 1

 UNION ALL

 SELECT b.Person,b.Start_timestamp,b.Stop_timestamp ,trim(a.Reason) || ',' || trim( b.Reason), LVL+1
 FROM MYTABLE a INNER JOIN MYREC b
 ON a.Person = b.Person
 AND a.Reason > b.Reason
 )

 SELECT Person,Start_timestamp,Stop_timestamp,Reason
 FROM MYREC
 QUALIFY RANK() OVER(PARTITION BY Person ORDER BY Reason DESC) = 1

Измените MYTABLE на ваше имя таблицы


Есть идеи?

10000