使用历史记录 table,我如何识别任何任务处于活动状态的每个时间段,并将数据集减少到不重叠的日期段

Using a history table, how can I identify each period of time in which any task is active, and reduce the data set to non-overlapping date periods

我在 Teradata 中有一个历史记录 table,其中包含有关某个帐户上发生的任务的信息。在典型的历史 table 方式中,存在的数据具有加载(有效自)和替换(有效至)日期。

在我的环境中,current/unterminated 记录有一个 1/1/3000 的日期,所有数据加载发生在系统中完成更改后的第二天午夜后不久 - 因此加载日期总是落后于开始日期一天。

一些样本数据可能看起来像这样(我已经添加了 Col "R" 来引用行号,它在 table 中不存在):

R ACCT_NUM TASK_NM TASK_STAT START_DT END_DT LD_DT RPLC_DT LGLC_DEL CURR_ROW
1 0123456 TASK_01 O 2018-05-01 NULL 2018-05-02 2018-05-16 N N
2 0123456 TASK_01 C 2018-05-01 2018-05-15 2018-05-16 2018-08-16 N N
3 0123456 TASK_01 C 2018-05-01 2018-05-15 2018-08-16 3000-01-01 Y Y
4 0123456 TASK_02 O 2018-05-05 NULL 2018-05-06 2018-05-19 N N
5 0123456 TASK_02 C 2018-05-05 2018-05-18 2018-05-19 2018-08-19 N N
6 0123456 TASK_03 O 2020-02-01 NULL 2020-02-02 2020-05-16 N N
7 0123456 TASK_03 C 2020-02-01 2020-02-15 2020-02-16 2020-04-16 N N
8 0123456 TASK_03 C 2020-02-01 2020-02-15 2020-04-16 3000-01-01 Y Y
9 0123456 TASK_04 C 2022-03-01 NULL 2022-03-02 3000-01-01 N Y

我苦苦挣扎的地方是 我需要确定每个唯一的时间段,其中 任何 任务在给定帐户上处于活动状态.如果多个任务在重叠时间段内处于活动状态,那么我需要确定第一个打开的任务的开始日期和最后一个重叠任务的结束日期。 (也有可能 TASK_02 可以在 TASK_01 完成之前同时开始和完成,所以在那种情况下我需要 start/end 与 task_01 相关的日期)。 =14=]

使用上面的示例数据,我想得到如下输出:

Account # Active Start Dt Active End Dt
0123456 2018-05-01 2018-05-19
0123456 2020-02-01 2018-02-15
0123456 2022-03-01 3000-01-01

任务 1 开始,然后任务 2 打开。任务 1 已完成,但任务 2 仍未完成。所以我需要任务 1 的开始日期(来自第 1 行)和任务 2 的结束日期(来自第 4 或 5 行)。稍后,任务 3 在其自己的时间范围内打开,这会创建一个新记录,最后任务 4 当前打开。

我试过很多东西都不成功,包括但很遗憾不限于:

由于隐私限制,我无法提供我编写的文字代码,但是,这里是模拟代码,任何人都可以提供指导,帮助我朝着正确的方向前进:

SELECT
   ACCT_NUM
   ,TASK_NM
   ,TASK_STAT
   ,START_DT
   ,END_DT
   --,[other 'unimportant' fields that can change and create change records]
   ,LD_DT - INTERVAL '1' DAY AS LD_DT --SIMULATE START_DT
   ,RPLC_DT - INTERVAL '1' DAY AS LD_DT --SIMULATE END_DT ON "TASK_STAT = 'O'" RECORDS
   ,LGLC_DEL
   ,CURR_ROW
FROM
   TBL_TASK_HIST
WHERE
   TASK_STAT = 'O'

很抱歉总结太长,试图提供 solid/clear 细节。

使用 Teradata 的 NORMALIZE 合并重叠或相遇的时期。根据您的示例数据,这似乎可行;您可能需要根据实际数据稍作调整。

SELECT ACCT_NUM, 
       BEGIN(PD) AS ACTIVE_START_DT,
       PRIOR(END(PD)) AS ACTIVE_END_DT
FROM 
 (SELECT NORMALIZE ACCT_NUM,
   PERIOD(START_DT,
       NEXT(COALESCE(END_DT,
          CASE WHEN TASK_STAT='O' and CURR_ROW='N'
          THEN START_DT
          ELSE DATE'3000-01-01' 
          END       )
            )
         ) AS PD
  FROM TBL_TASK_HIST
 ) N
 ORDER BY ACCT_NUM, ACTIVE_START_DT;

NORMALIZE 需要 PERIOD 数据类型,因此我们在内部查询中使用 PERIOD() 构造函数,在外部查询中使用 BEGIN()END() 函数转换回两列。由于 PERIOD 不包括结束 date/time 界限(它是一个“closed/open 间隔”),我们使用 NEXT()PRIOR() 函数调整结束值。

也许您可以将逻辑基于 LD_DT、RPLC_DT 以避免必须处理 NULL END_DT,但如果可能的话最好使用“业务”列而不是ETL 元数据。