Partition to calculate the difference between two different values (including values which only appear one time within the partition)
04:57 17 Nov 2025

DB-Fiddle

CREATE TABLE inventory (
    id SERIAL PRIMARY KEY,
    stock_date DATE,
    product VARCHAR,
    stock_balance INT
);

INSERT INTO inventory
(stock_date, product, stock_balance
)
VALUES 
('2025-10-01','prod_01','100'),
('2025-10-01','prod_02','500'),
('2025-10-31','prod_01','800'),
('2025-10-31','prod_02','600'),
('2025-10-31','prod_03','700'),
('2025-10-31','prod_04','400');

Expected Result:

product  |   stock_date |  stock_balance |   change  |   
---------|--------------|----------------|-----------|-
prod_01  |  2025-10-01  |      100       |   700     |
prod_01  |  2025-10-31  |      800       |   700     |
prod_02  |  2025-10-01  |      500       |   100     |
prod_02  |  2025-10-31  |      600       |   100     |
prod_03  |  2025-10-01  |        0       |   400     |
prod_03  |  2025-10-31  |      400       |   400     |
prod_04  |  2025-10-01  |        0       |   700     |
prod_04  |  2025-10-31  |      700       |   700     |

I want to display for each product in the table the stock_balance on 2025-10-01 and 2025-10-31 and calculate the change of the stock_balance between these two dates in a separate column.

So for I have been able to develop this query:

select
t1.product as product,
t1.stock_date as stock_date,
t1.stock_balance as stock_balance,
LAST_VALUE(t1.stock_balance) OVER (PARTITION BY t1.product ORDER BY stock_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) - 
FIRST_VALUE(t1.stock_balance) OVER (PARTITION BY t1.product ORDER BY stock_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as change
from
  
  (select
  product as product,
  stock_date as stock_date,
  sum(stock_balance) as stock_balance
  from inventory
  group by 1,2
  order by 1,2 desc) t1

group by 1,2,3
order by 1,2,3;

The query provides the result correctly for prod_01 and prod_02.
However, for prod_03 and prod_04 it is not correct. I assume this is because they appear only on stock_date = 2025-10-31.

How do I need to modify the query to also get these products displayed as in the expected results?
(I guess somehow I need to insert an empty row for these products for stock_date = 2025-10-01)

sql postgresql