I have a query from my postgres tables that looks like this:
date | sku | incoming_unit_qty | incoming_unit_cost | landed_unit_qty |
---|---|---|---|---|
2023-08-01 | sku-1 | 1,000 | $3.00 | 0 |
2023-08-01 | sku-2 | 2,000 | $2.00 | 0 |
2023-08-01 | sku-3 | 3,000 | $1.00 | 0 |
2023-09-01 | sku-1 | 1,000 | $3.50 | 500 |
2023-09-01 | sku-2 | 2,000 | $2.50 | 1,000 |
2023-09-01 | sku-3 | 3,000 | $1.50 | 1,500 |
2023-10-01 | sku-1 | 1,000 | $4.00 | 750 |
2023-10-01 | sku-2 | 2,000 | $3.00 | 1,500 |
2023-10-01 | sku-3 | 3,000 | $2.00 | 2,250 |
2023-11-01 | sku-1 | 1,000 | $3.50 | 250 |
2023-11-01 | sku-2 | 2,000 | $2.50 | 500 |
2023-11-01 | sku-3 | 3,000 | $1.50 | 750 |
I am trying to generate a view
that would calculate for each sku and each date, the weighted average cost. The result should look as follows:
date | sku | incoming_unit_qty | incoming_unit_cost | landed_unit_qty | landed_unit_cost | average_cost |
---|---|---|---|---|---|---|
2023-08-01 | sku-1 | 1,000 | $3.00 | 0 | $0.00 | $3.00 |
2023-08-01 | sku-2 | 2,000 | $2.00 | 0 | $0.00 | $2.00 |
2023-08-01 | sku-3 | 3,000 | $1.00 | 0 | $0.00 | $1.00 |
2023-09-01 | sku-1 | 1,000 | $3.50 | 500 | $3.00 | $3.33 |
2023-09-01 | sku-2 | 2,000 | $2.50 | 1,000 | $2.00 | $2.33 |
2023-09-01 | sku-3 | 3,000 | $1.50 | 1,500 | $1.00 | $1.33 |
2023-10-01 | sku-1 | 1,000 | $4.00 | 750 | $3.33 | $3.71 |
2023-10-01 | sku-2 | 2,000 | $3.00 | 1,500 | $2.33 | $2.71 |
2023-10-01 | sku-3 | 3,000 | $2.00 | 2,250 | $1.33 | $1.71 |
2023-11-01 | sku-1 | 1,000 | $3.50 | 250 | $3.71 | $3.54 |
2023-11-01 | sku-2 | 2,000 | $2.50 | 500 | $2.71 | $2.54 |
2023-11-01 | sku-3 | 3,000 | $1.50 | 750 | $1.71 | $1.54 |
How can I achieve this?
I have tried the below recursive CTE query, which results in the following error message recursive reference to query "lc" must not appear within a subquery LINE 15: (select average_cost from lc where date < lc.date and sku = lc.sku order by date desc limit 1) as landed_unit_cost
. While I understand the error message, I cannot find a solution that doesn't involve a recursive subquery.
with recursive lc as (
(select distinct on (sku)
*,
0 as landed_unit_cost,
incoming_unit_cost as average_cost
from lc_history
order by sku, date)
union
select
l.*,
(l.incoming_unit_qty*l.incoming_unit_cost + l.landed_unit_qty*l.landed_unit_cost) / (l.incoming_unit_qty + l.landed_unit_qty) as average_cost
from (
select
*,
(select average_cost from lc where date < lc.date and sku = lc.sku order by date desc limit 1) as landed_unit_cost
from lc_history
) l
)
select * from lc order by date, sku;
Thanks for your help!
I ended up writing a for loop in PL/pgSQL. It's not as elegant as an SQL query, but it works.