Пока l oop для Терадата - PullRequest
0 голосов
/ 16 января 2020

мир.

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

Existing Data

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

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

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

Output data

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

Ответы [ 2 ]

2 голосов
/ 16 января 2020

Нет необходимости в рекурсии (и очень трудно писать) или в oop над курсором.

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 '30' 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, вы можете упростить вычисление группы, но я не смог написать этот синтаксис c ad ho c: -)

0 голосов
/ 16 января 2020

Вы можете добиться этого, используя 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 на ваше имя таблицы

...