有条件 运行 总计
Conditional running total
我必须在 Redshift 中做一件有趣的事情。比如说,我有一个像这样的 table:
index,total,delta
0,3,null
1,5,2
2,10,5
3,11,1
4,null,4
5,null,6
6,null,2
其中 delta
是每个 total
与上一行的 total
之间的差异。在这里,我的 delta
s 来自与我的 total
s 不同的来源,因此可以接收 delta
s 而不接收更新的 total
s。
如何根据 delta
推算 total
?像这样:
index,total,delta
0,3,null
1,5,2
2,10,5
3,11,1
4,15,4
5,21,6
6,23,2
我在 NVL(total, LAST_VALUE(total IGNORE NULLS) OVER (ORDER BY index ROWS UNBOUNDED PRECEDING) + SUM(delta) OVER (ORDER BY index ROWS UNBOUNDED PRECEDING)
附近的某个地方闲逛,但这并不能完全做到 - 我只想 SUM
delta
有没有对应的total
.
您可以使用:
-- creating subgroups
WITH cte AS (
SELECT *, SUM(total IS NOT NULL::int) OVER(ORDER BY index) s
FROM tab
)
SELECT index,
CASE WHEN total IS NULL
THEN SUM(COALESCE(total,0) + delta) OVER(PARTITION BY s ORDER BY index)
-FIRST_VALUE(delta) OVER(PARTITION BY s ORDER BY index)
-- running total starting from first not null total + delta
-- decreased by first delta
ELSE total
END AS total
,delta
FROM cte
ORDER BY index;
输出:
┌────────┬────────┬───────┐
│ index │ total │ delta │
├────────┼────────┼───────┤
│ 0 │ 3 │ │
│ 1 │ 5 │ 2 │
│ 2 │ 10 │ 5 │
│ 3 │ 11 │ 1 │
│ 4 │ 15 │ 4 │
│ 5 │ 21 │ 6 │
│ 6 │ 23 │ 2 │
└────────┴────────┴───────┘
编辑:
其实不需要FIRST_VALUE
:
WITH cte AS (
SELECT *, SUM(total IS NOT NULL::int) OVER(ORDER BY index) s
FROM tab
)
SELECT index,
CASE WHEN total IS NULL
THEN SUM(COALESCE(total,0)
+ CASE WHEN total IS NOT NULL THEN 0 ELSE delta END)
OVER(PARTITION BY s ORDER BY index)
ELSE total
END AS total
,delta
FROM cte
ORDER BY index;
我必须在 Redshift 中做一件有趣的事情。比如说,我有一个像这样的 table:
index,total,delta
0,3,null
1,5,2
2,10,5
3,11,1
4,null,4
5,null,6
6,null,2
其中 delta
是每个 total
与上一行的 total
之间的差异。在这里,我的 delta
s 来自与我的 total
s 不同的来源,因此可以接收 delta
s 而不接收更新的 total
s。
如何根据 delta
推算 total
?像这样:
index,total,delta
0,3,null
1,5,2
2,10,5
3,11,1
4,15,4
5,21,6
6,23,2
我在 NVL(total, LAST_VALUE(total IGNORE NULLS) OVER (ORDER BY index ROWS UNBOUNDED PRECEDING) + SUM(delta) OVER (ORDER BY index ROWS UNBOUNDED PRECEDING)
附近的某个地方闲逛,但这并不能完全做到 - 我只想 SUM
delta
有没有对应的total
.
您可以使用:
-- creating subgroups
WITH cte AS (
SELECT *, SUM(total IS NOT NULL::int) OVER(ORDER BY index) s
FROM tab
)
SELECT index,
CASE WHEN total IS NULL
THEN SUM(COALESCE(total,0) + delta) OVER(PARTITION BY s ORDER BY index)
-FIRST_VALUE(delta) OVER(PARTITION BY s ORDER BY index)
-- running total starting from first not null total + delta
-- decreased by first delta
ELSE total
END AS total
,delta
FROM cte
ORDER BY index;
输出:
┌────────┬────────┬───────┐
│ index │ total │ delta │
├────────┼────────┼───────┤
│ 0 │ 3 │ │
│ 1 │ 5 │ 2 │
│ 2 │ 10 │ 5 │
│ 3 │ 11 │ 1 │
│ 4 │ 15 │ 4 │
│ 5 │ 21 │ 6 │
│ 6 │ 23 │ 2 │
└────────┴────────┴───────┘
编辑:
其实不需要FIRST_VALUE
:
WITH cte AS (
SELECT *, SUM(total IS NOT NULL::int) OVER(ORDER BY index) s
FROM tab
)
SELECT index,
CASE WHEN total IS NULL
THEN SUM(COALESCE(total,0)
+ CASE WHEN total IS NOT NULL THEN 0 ELSE delta END)
OVER(PARTITION BY s ORDER BY index)
ELSE total
END AS total
,delta
FROM cte
ORDER BY index;