有条件的总计

时间:2018-10-15 19:53:53

标签: sql amazon-redshift window-functions running-total

我在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

1 个答案:

答案 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;

db<>fiddle demo

输出:

┌────────┬────────┬───────┐
│ 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;

db<>fiddle demo2