I have the following table in PostgresSQL, and I would like to find a function or logic to store the result of the first row in a new column to be used in the second row and so on.
The formula is (stock + pending-sells), so for the first row, the result is "2," and that should become my new stock value for the second row. Therefore, the result is 2 + 0 + 0 = 2. For the next row (row 3), my new stock is (2 + 1 – 0), resulting in 3, and the same with the following rows.
Is there a way to achieve this with SQL, or do I need to try outside with Python?
idx | date | ID | stock | pending | sells |
---|---|---|---|---|---|
0 | 2023-07-01 | 187760 | 1 | 1 | 0 |
1 | 2023-08-01 | 187760 | 1 | 0 | 0 |
2 | 2023-09-01 | 187760 | 1 | 1 | 0 |
3 | 2023-10-01 | 187760 | 1 | 0 | 1 |
4 | 2023-11-01 | 187760 | 1 | 0 | 0 |
5 | 2023-12-01 | 187760 | 1 | 0 | 0 |
I tried with lag() and lead() with no luck so far.
The "expected result" column with the formula (stock+pending-sells) for this table
idx | date | ID | stock | pending | sells | expected_results |
---|---|---|---|---|---|---|
0 | 2023-07-01 | 187760 | 1 | 1 | 0 | 2 |
1 | 2023-08-01 | 187760 | 2 | 0 | 0 | 2 |
2 | 2023-09-01 | 187760 | 2 | 1 | 0 | 3 |
3 | 2023-10-01 | 187760 | 3 | 0 | 1 | 2 |
4 | 2023-11-01 | 187760 | 2 | 0 | 0 | 2 |
5 | 2023-12-01 | 187760 | 2 | 0 | 0 | 2 |
The "expected result" column is calculated by considering the result of the previous row’s calculation as the new stock for the next row.
I tried with this
with cte_ as
(
SELECT
nc.date,
nc.id,
RANK() OVER (PARTITION BY nc.id ORDER BY nc.date ASC) AS ranking,
nc.stock,
nc.pending,
nc.sells,
nc.stock + nc.pending - nc.sells AS formula
FROM test_table nc
where nc.id='187760'
)
select *,
lag(c.formula) OVER (PARTITION BY c.id ORDER BY c.date),
lag(c.formula) OVER (PARTITION BY c.id ORDER BY c.date)+c.pending-c.sells as test
from cte_ as c
But the result column is
results |
---|
NULL |
2 |
2 |
1 |
0 |
Thank you.
Best regards.
2
Answers
The following query returns the results as shown in the original post:
This query uses
sum
as a window function with an implicit window frame ofROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
to aggregatepending
andsells
to be added the currentstock
.This query addresses the revised post:
It makes no sense to do simple arithmetic calculations like this outside of the database.
It is wrong to have the
stock
column populated with the value1
in your table. If you are recalculating stock based solely on movements, then you need a starting value that you apply your movements to. Most systems use the current (perpetual) inventory as the starting point and calculate backwards.I used it as the initial stock level with
first_value()
.Working fiddle