【问题标题】:Teradata Window/Rolling Sum under Multiple Conditions多条件下的 Teradata Window/Rolling Sum
【发布时间】:2015-11-03 23:15:47
【问题描述】:

我正在使用 Teradata SQL Assistant 14.10 并遇到以下问题:

我有一个计算出的经过时间列表,我需要创建一个列来标记何时

  • a) 经过时间总和首次超过 20 分钟的行
  • b) 之后每次经过的时间总和超过 15 分钟的行

这里的困难在于,用于设置标志的滚动和需要在满足每个条件后变为 0。请参阅下面的结果集,其中 FLAG 是基于上述条件的所需输出列,原因列解释了为什么要标记它。

RN  REPORT_DT   SEG_CD  NUM_F   T1          T2          ELAPSED_TIME    FLAG    REASON
1   6/22/2015   STATION 881     18:33:00    17:30:00    63              1       63 >= 20 min for first time
2   6/22/2015   STATION 881     18:45:00    18:33:00    12              0       12 < 15
3   6/22/2015   STATION 881     19:00:00    18:45:00    15              1       12 + 15 >= 15
4   6/22/2015   STATION 881     19:15:00    19:00:00    15              1       15 >= 15
5   6/22/2015   STATION 881     19:30:00    19:15:00    15              1       15 >= 15
6   6/22/2015   STATION 881     19:40:00    19:30:00    10              0       10 < 15
7   6/22/2015   STATION 881     19:50:00    19:40:00    10              1       10 + 10 >= 15
8   6/22/2015   STATION 881     20:00:00    19:50:00    10              0       10 < 15
9   6/22/2015   STATION 881     20:10:00    20:00:00    10              1       10 + 10 >= 15

我尝试了各种 SUM()OVER(PARTITION BY ORDER BY RESET WHEN) 类型的查询,我认为这是正确的方向,但似乎无法获得任何预期的结果。

非常感谢任何建议!提前致谢!

【问题讨论】:

  • 唉,你不能轻易地用解析函数来做这个计算。问题是您有余数(例如第 3 行中有 3 个)。您忽略了这个额外的超量,这意味着后续行必须知道所有先前断点发生的确切位置。
  • 哇 - 感谢您的快速响应。很高兴知道这是不可能的,至少让我免于整天绞尽脑汁。
  • 每个 PARTITION 的行数和最大行数是多少?
  • 我总共有不到 200k 行,上面的摘录是单个分区的示例(我已经对 REPORT_DT、SEG_CD 和 NUM_F 进行了分区)。虽然每个分区的行数是可变的,但我相信最大的一个包含 47 行。

标签: sql sum teradata cumulative-sum


【解决方案1】:

我发现返回这样的结果的唯一方法是利用递归。

如果将数据具体化为Multiset Volatile Table,首先将分区列(REPORT_DT,SEG_CD,NUM_F)作为主索引,然后开始递归,您将获得最快的速度:

WITH RECURSIVE cte AS
(   
SELECT
  RN,
  REPORT_DT,
  SEG_CD,
  NUM_F,
  T1,
  T2,
  ELAPSED_TIME,
  CASE WHEN ELAPSED_TIME >= 20 
       THEN 0 
       ELSE ELAPSED_TIME
  END AS sum_ELAPSED_TIME,
  CASE WHEN sum_ELAPSED_TIME = 0 
       THEN 1 
       ELSE 0
  END AS FLAG
FROM vt
WHERE rn = 1

UNION ALL

SELECT
  vt.RN,
  vt.REPORT_DT,
  vt.SEG_CD,
  vt.NUM_F,
  vt.T1,
  vt.T2,
  vt.ELAPSED_TIME,
  CASE WHEN cte.sum_ELAPSED_TIME + vt.ELAPSED_TIME >= 15 
       THEN 0 
       ELSE cte.sum_ELAPSED_TIME + vt.ELAPSED_TIME 
  END AS new_ELAPSED_TIME,
  CASE WHEN new_ELAPSED_TIME = 0
       THEN 1 
       ELSE 0
  END AS FLAG
FROM vt 
JOIN cte 
  ON vt.REPORT_DT = cte.REPORT_DT
 AND vt.SEG_CD = cte.SEG_CD
 AND vt.NUM_F = cte.NUM_F
 AND vt.rn = cte.rn + 1
) 
SELECT * FROM cte

【讨论】:

  • 这太棒了 - 谢谢!
猜你喜欢
  • 2013-09-09
  • 1970-01-01
  • 2022-12-28
  • 1970-01-01
  • 2012-03-04
  • 1970-01-01
  • 1970-01-01
  • 2017-12-11
  • 2023-04-10
相关资源
最近更新 更多