Co třeba:
--DROP TABLE #Stock
create table #Stock
(
Transection_Date Date,
transectionType varchar(20),
Unit numeric(18,2),
UnitCost numeric(18,2)
)
--Mar 1 Beginning Inventory 68 units @ $15.00 per unit
--5 Purchase 140 units @ $15.50 per unit
--9 Sale 94 units @ $19.00 per unit
--11 Purchase 40 units @ $16.00 per unit
--16 Purchase 78 units @ $16.50 per unit
--20 Sale 116 units @ $19.50 per unit
--29 Sale 62 units @ $21.00 per unit
insert into #Stock select '2014-03-01', 'Beginning Inventory', 68, 15
insert into #Stock select '2014-03-05', 'Purchase', 140, 15.50
insert into #Stock select '2014-03-09', 'Sale', 94, 19
insert into #Stock select '2014-03-11', 'Purchase', 40, 16
insert into #Stock select '2014-03-16', 'Purchase', 78, 16.5
insert into #Stock select '2014-03-20', 'Sale', 116, 19.50
insert into #Stock select '2014-03-29', 'Sale', 62, 21.00
;WITH UnitsCTE
AS
(
-- GET Total Units Left
SELECT SUM(
CASE transectionType
WHEN 'Purchase' Then Unit
When 'Sale' THEN Unit * -1
ELSE Unit END) AS Units
FROM #Stock
), PurchaseCTE
AS
(
-- Get only purchases in reverse order
SELECT Unit, UnitCost, Transection_Date, ROW_NUMBER() OVER (ORDER BY Transection_Date DESC ) AS RN
FROM #Stock
WHERE transectionType <> 'Sale'
),
UnitCost
AS
(
-- Recursive CTE to get number of units left at each price
SELECT CASE WHEN Unit > UnitsCTE.Units THEN UnitsCTE.Units ELSE Unit END As Units, UnitCost
FROM PurchaseCTE
CROSS APPLY UnitsCTE
WHERE RN = 1
UNION ALL
SELECT CASE WHEN P1.Unit > (UnitsCTE.Units - (SELECT SUM(Unit) FROM PurchaseCTE P3 WHERE p3.RN < p1.RN))
THEN CASE WHEN (UnitsCTE.Units - (SELECT SUM(Unit) FROM PurchaseCTE P3 WHERE p3.RN < p1.RN)) < 0 THEN 0
ELSE (UnitsCTE.Units - (SELECT SUM(Unit) FROM PurchaseCTE P3 WHERE p3.RN < p1.RN)) END
ELSE P1.Unit END,
P1.UnitCost
FROM PurchaseCTE P1
INNER JOIN PurchaseCTE P2
ON P1.RN = P2.RN + 1
CROSS APPLY UnitsCTE
)
SELECT SUM(Units), SUM(UnitCost * Units) / SUM(Units) AS UnitCost, SUM(Units * UnitCost) AS TotalCost
FROM UnitCost
WHERE Units > 0