Условный промежуточный итог - PullRequest
0 голосов
/ 15 октября 2018

У меня есть интересная вещь, которую я должен сделать в 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 s, для которых естьне соответствуют total.

1 Ответ

0 голосов
/ 15 октября 2018

Вы можете использовать:

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

...