我在Redshift中要做一件有趣的事情。说,我有一张这样的桌子:
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
来自与我的total
不同的来源,因此可以接收delta
而不必接收更新的total
。
如何根据total
来估算delta
?像这样:
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
。
答案 0 :(得分:1)
您可以使用:
-- 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;