database - Teradata TD_NORMALIZE 无助于合并相邻时段
问题描述
我认为使用 CTE 和 TD_NORMALIZE_MEET 会帮助我。我有多行,说
**FIELD1 | FIELD2 | FIELD3 | FIELD4 | START_DT | END_DT**
abcd1 | efgh1 | hijk1 | lmno1 | 2019/09/23 | 2019/09/30
abcd1 | efgh1 | hijk1 | lmno1 | 2019/10/01 | 2019/10/25
abcd1 | efgh1 | hijk1 | lmno1 | 2019/11/01 | 2019/11/30
abcd1 | efgh1 | hijk1 | lmno1 | 2019/12/01 | 2019/12/25
abcd1 | efgh1 | hijk1 | lmno1 | 2019/12/26 | 2020/01/10
abcd1 | efgh1 | hijk1 | lmno1 | 2020/01/15 | 2020/01/30
abcd1 | efgh1 | hijk1 | lmno1 | 2020/01/31 | 2020/03/20
abcd1 | efgh1 | hijk1 | lmno1 | 2020/03/28 | 2020/05/25
abcd1 | efgh1 | hijk1 | lmno1 | 2020/06/01 | 2020/09/01
这些应该作为
**FIELD1 | FIELD2 | FIELD3 | FIELD4 | START_DT | END_DT**
abcd1 | efgh1 | hijk1 | lmno1 | 2019/09/23 | 2019/10/25
abcd1 | efgh1 | hijk1 | lmno1 | 2019/11/01 | 2020/01/10
abcd1 | efgh1 | hijk1 | lmno1 | 2020/01/15 | 2020/03/20
abcd1 | efgh1 | hijk1 | lmno1 | 2020/03/28 | 2020/05/25
abcd1 | efgh1 | hijk1 | lmno1 | 2020/06/01 | 2020/09/01
但是,TD_NORMALIZE_MEET 并没有帮助。尝试了 TD_NORMALIZE_OVERLAP_MEET 和所有其他技巧。任何帮助是极大的赞赏。我什至尝试通过在结束日期添加一天来使用 TD_NORMALIZE_OVERLAP_MEET,但这会以不同的方式混淆数据。因此,我必须遵守日期,但以将它们组合在一起的方式合并日期,以获得最低连续期间的最小开始日期和最高连续期间的最大结束日期。
解决方案
因此,为了继续解决我的问题,并且感谢同样在这里的人们提供的一些精彩提示,我必须要有创意。一个是使用 CTE(公用表表达式),另一个是为我拥有的 4 个字段组创建一个不同的 ID 字段,因为我以某种方式传递了任何非整数并且多个字段不适用于我使用的 TD_NORMALIZE_OVERLAP_MEET。
我仍在寻找一种解决方案来使用多个组列,非 INT 类型与 TD_NORMALIZE... 函数。请协助。
正如 Fred 上面建议的那样,如果下一个开始日期相邻,我确实必须延长结束日期以与下一个开始日期重叠。我使用 DENSE_RANK 以便数字从一组到另一组是连续的。
所以
CREATE VOLATILE TABLE TBL1 AS
(
SELECT
FIELD1,
FIELD2,
FIELD3,
FIELD4,
DENSE_RANK() OVER(PARTITION BY FIELD1, FIELD2, FIELD3, FIELD4
ORDER BY START_DT ASC) AS GRP_RANK,
START_DT,
END_DT,
PERIOD(START_DT, END_DT + 1) AS COVERED_PERIOD
FROM MYTABLE
) WITH DATA
PRIMARY INDEX (FIELD1, FIELD2, FIELD3, FIELD4, SAME_DAY_FLAG)
INDEX (GRP_RANK) ON COMMIT PRESERVE ROWS;
用它来创建合并表。
CREATE VOLATILE TABLE TBL_MERGED AS
(
WITH CTE(GRP_RANK, COVERED_PERIOD) AS
(
SELECT
GRP_RANK,
COVERED_PERIOD
FROM TBL1
)
SELECT * FROM TABLE
( TD_SYSFNLIB.TD_NORMALIZE_OVERLAP_MEET(NEW VARIANT_TYPE(CTE.GRP_RANK), CTE.COVERED_PERIOD)
RETURNS(GRP_RANK INT, COVERED_PERIOD PERIOD(DATE))
HASH BY GRP_RANK
LOCAL ORDER BY GRP_RANK, COVERED_PERIOD
) AS TBL_ROWS
)WITH DATA ON COMMIT PRESERVE ROWS;
然后我用我的 tbl1 加入了它
SELECT
A.FIELD1,
A.FIELD2,
A.FIELD3,
A.FIELD4,
A.GRP_RANK,
A.COVERED_PERIOD,
MIN(A.START_DT) AS START_DT,
MAX(A.END_DT) AS END_DT
FROM TBL1 AS A
JOIN TBL_MERGED AS B
ON A.GRP_RANK = B.GRP_RANK
AND A.COVERED_PERIOD OVERLAPS B.COVERED_PERIOD
GROUP BY 1,2,3,4,5,6
ORDER BY 1,2,3,4,7
推荐阅读
- java - JAVA窗口设计为空白
- c# - 用 ViewModel 中的数据填充 @Html.DropDownListFor
- javascript - 如何检查元素的位置?
- c# - 如何从窗口内的另一个类调用方法?
- php - PHP 复制和操作 XML
- javascript - 使用 OR ( | ) 时的正则表达式非捕获组
- python - 在 Dart 中,Python 的 try...catch...else 最惯用的替代方法是什么?
- php - 如何正确配置 Guzzle 以从其他服务器下载 zip 文件
- migration - 语法错误或访问冲突:1075 表定义不正确;只能有一个自动列,并且必须将其定义为键
- php - 登录用户的电子邮件确认,Behat 测试