使用历史记录 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 当前打开。
我试过很多东西都不成功,包括但很遗憾不限于:
- 只获取 'Task Status = Open' 条记录,因为替换日期将更新为结束日期,但从这里我不确定如何最好地进行比较以解决重叠的时间范围。
- 利用 Lead/Lag 函数来识别下一个记录加载日期,但同样,由于任务可以按任何顺序发生,因此这会创建不正确的时间范围,因为我无法动态识别我需要的下一个替换日期
- 尝试在子查询中识别打开任务的唯一加载日期,然后自行加入任务table但这只会创建重复项,其中多个事物在给定日期有效
由于隐私限制,我无法提供我编写的文字代码,但是,这里是模拟代码,任何人都可以提供指导,帮助我朝着正确的方向前进:
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 元数据。
我在 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 当前打开。
我试过很多东西都不成功,包括但很遗憾不限于:
- 只获取 'Task Status = Open' 条记录,因为替换日期将更新为结束日期,但从这里我不确定如何最好地进行比较以解决重叠的时间范围。
- 利用 Lead/Lag 函数来识别下一个记录加载日期,但同样,由于任务可以按任何顺序发生,因此这会创建不正确的时间范围,因为我无法动态识别我需要的下一个替换日期
- 尝试在子查询中识别打开任务的唯一加载日期,然后自行加入任务table但这只会创建重复项,其中多个事物在给定日期有效
由于隐私限制,我无法提供我编写的文字代码,但是,这里是模拟代码,任何人都可以提供指导,帮助我朝着正确的方向前进:
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 元数据。