I have a table that contains a list of (year,points) and an initial number of points (100 in this example). I want to list each year with the (running) amount of points consumed:
create table test (
year int
,points int
)
INSERT INTO test
SELECT generate_series(2000,2004),generate_series(10,50,10);
The result should look like this:
| year | points | available | consumed | remaining |
|---|---|---|---|---|
| 2000 | 10 | 100 | 10 | 90 |
| 2001 | 20 | 90 | 20 | 70 |
| 2002 | 30 | 70 | 30 | 40 |
| 2003 | 40 | 40 | 40 | 0 |
| 2004 | 50 | 0 | 0 | 0 |
The available column is just COALESCE( LAG(remaining) OVER (ORDER BY year) ,100),
consumed is calculated with something like LEAST(points,available) and remaining is available-consumed.
So my query could look like this but of course it is not valid because every field depends on another one:
WITH config AS (
SELECT 100 AS initial
)
select year, points
,available
,consumed
,remaining
FROM test
CROSS JOIN config
CROSS JOIN LATERAL (
SELECT LEAST(points,available) AS consumed
) y
CROSS JOIN LATERAL (
SELECT available-consumed AS remaining
) z
CROSS JOIN LATERAL (
SELECT COALESCE( LAG(remaining) OVER w ,initial) AS available
WINDOW w AS (ORDER BY year)
) x
What is the proper way of writing such constructs ? Should I use SUM() OVER () to calculate some kind of running total?