I’m trying to write a SQL query (SQL Server 2005) to calculate the current value of inventory on hand. I have a table that looks like this:
ID | QTY | BasePrice
1 | 10 | 100
2 | -2 | 0
3 | -2 | 0
4 | 10 | 200
5 | -2 | 0
Where qty > 0 is stock coming in and < 0 is stock going out. Negative quantities don’t record a BasePrice due to other business rules. Base price is price per unit.
I need to find either the average price OR total price of inventory that is still on hand. So the resulting column needs to be:
ID | QTY | BasePrice | TotalPrice | AveragePrice
1 | 10 | 100 | 1000 | 100
2 | -2 | 0 | 800 | 100
3 | -2 | 0 | 600 | 100
4 | 10 | 200 | 2600 | 162.50
5 | -2 | 0 | 2275 | 162.50
I was able to work out this:
select g1.projectionID,
g1.qty,
g1.basePrice,
((sum(isnull(g2.basePrice,0)))) * sum(isnull(g2.Qty,0)) + (g1.Qty * (case when g1.Qty < 0 THEN (sum(isnull(g2.basePrice,0))) ELSE g1.BasePrice END)) As CurrenctValueOfStockOnHand
from test g1
left join test g2 on g2.projectionID < g1.projectionID
group by g1.ProjectionID, g1.Qty, g1.BasePrice
Which gives:
ID| QTY| BasePrice | TotalPrice
1 | 10 | 100.0000 | 1000.0000
2 | -2 | 0.0000 | 800.0000
3 | -2 | 0.0000 | 600.0000
4 | 10 | 200.0000 | 2600.0000
5 | -2 | 0.0000 | 4200.0000
But as you can see it gives the wrong values after the 2nd lot of inventory is added (after ID 4).
We currently have C# code that loops through each record and keeps a running total. For large stocks this takes far too long. If the only option is to use a cursor then we’ll keep our C# code.
After Randy mentioned using LAG function I had a quick Google search for LAG function in SQL Server and found code using a table variable and an update statement.
I’m still not convinced this is the best answer, but it does give the correct output without using a cursor