Teradata 的 While 循环

While loop for Teradata

世界。

我正在尝试找到一种将多个事件编译在一起的方法。数据如下所示:

基本上,它是一系列带有事件日志的行数据

我想生成这些行事件的聚合,这样如果新事件在另一个结束后的 30 秒内发生,它会将时间合并在一起。但是,如果事件日志没有邻接事件,则不会捕获它。这些事件是 'person' 特定的。

我设想输出看起来像这样:

我的直觉建议使用某种 while 循环,但我不确定从哪里开始

您可以使用 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 更改为您的表名

不需要递归(而且很难编写)或游标循环。

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 你可以简化组计算,但我不能写这个 syntaxc ad hoc :-)