考虑一个代表"事件之间时间的列":
(5, 40, 3, 6, 0, 9, 0, 4, 5, 18, 2, 4, 3, 2)
我想把它们分成30个桶,但重置的桶。期望的结果:
(0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2)
这是因为,当我们累计达到30时,我们会重置"并再次开始计算。那么,5 + 40> 30,我们下降到零并开始累积添加,直到我们达到30 ...(3 + 6 + 0 ...),这发生在我们达到第10个元素== 18时。
这可以通过Reduce
函数实现(参见this answer),但我无法弄清楚如何在Teradata中实现它?就像我需要能够在同一个电话中引用相同的OVER(PARTITION BY ...
一样。
打破逻辑,这是Excel中的一个例子:
其中,B2
具有公式:=IF(B1<30, B1+A2, A2)
,并相应地向下拖动。然后,列C
会检查列B
是否> = 30,而列D
是列B
的简单字符。
答案 0 :(得分:3)
我知道在Teradata中执行此操作的唯一方法是使用递归CTE。因为我很懒,所以让我们简化一下,说你想要在你的运行总和大于2时重置。 为此创建并填充一个非常简单的易变表:
CREATE VOLATILE TABLE vt1
(
foo VARCHAR(10)
, counter INTEGER
, bar INTEGER
)
ON COMMIT PRESERVE ROWS;
INSERT INTO vt1 VALUES ('a', 1, '1');
INSERT INTO vt1 VALUES ('a', 2, '2');
INSERT INTO vt1 VALUES ('a', 3, '2');
INSERT INTO vt1 VALUES ('a', 4, '4');
INSERT INTO vt1 VALUES ('a', 5, '1');
INSERT INTO vt1 VALUES ('b', 1, '3');
INSERT INTO vt1 VALUES ('b', 2, '1');
INSERT INTO vt1 VALUES ('b', 3, '1');
INSERT INTO vt1 VALUES ('b', 4, '2');
这是实际的选择:
WITH RECURSIVE cte (foo, counter, bar, rsum) AS
(
SELECT
foo
, counter
, bar
, bar AS rsum
FROM
vt1
QUALIFY ROW_NUMBER() OVER (PARTITION BY foo ORDER BY counter) = 1
UNION ALL
SELECT
t.foo
, t.counter
, t.bar
, CASE WHEN cte.rsum < 3 THEN t.bar + cte.rsum ELSE t.bar END
FROM
vt1 t JOIN cte ON t.foo = cte.foo AND t.counter = cte.counter + 1
)
SELECT
cte.*
, CASE WHEN rsum < 5 THEN 0 ELSE 1 END AS tester
FROM
cte
ORDER BY
foo
, counter
;
最终会给我们:
╔═════╦═════════╦═════╦══════╦════════╗
║ foo ║ counter ║ bar ║ rsum ║ tester ║
╠═════╬═════════╬═════╬══════╬════════╣
║ a ║ 1 ║ 1 ║ 1 ║ 0 ║
║ a ║ 2 ║ 2 ║ 3 ║ 0 ║
║ a ║ 3 ║ 2 ║ 5 ║ 1 ║
║ a ║ 4 ║ 4 ║ 4 ║ 0 ║
║ a ║ 5 ║ 1 ║ 5 ║ 1 ║
║ b ║ 1 ║ 3 ║ 3 ║ 0 ║
║ b ║ 2 ║ 1 ║ 4 ║ 0 ║
║ b ║ 3 ║ 1 ║ 5 ║ 1 ║
║ b ║ 4 ║ 2 ║ 2 ║ 0 ║
╚═════╩═════════╩═════╩══════╩════════╝
case语句为我们处理重置。
这有点难看,但我从来没有能够以任何其他方式使用它。