I have an inventory table. Inventory table SQL:
CREATE TABLE INVENTORY
(
    INVENTORY_ID             SERIAL PRIMARY KEY,
    INVENTORY_DATE           date NOT NULL,
    ITEM_NAME                text NOT NULL,
    PURCHASED_QUANTITY       INTEGER DEFAULT 0,
    SOLD_QUANTITY            INTEGER DEFAULT 0,
    AMOUNT                   MONEY NOT NULL,
    TOTAL                    MONEY NOT NULL       
);
INSERT INTO INVENTORY(INVENTORY_DATE, ITEM_NAME, PURCHASED_QUANTITY, SOLD_QUANTITY, AMOUNT, TOTAL)
SELECT '1/1/2014'::date, 'ITEM-001', 10, NULL, 100, 1000 UNION ALL
SELECT '1/2/2014'::date, 'ITEM-001', NULL, 2, 200, 400 UNION ALL
SELECT '1/3/2014'::date, 'ITEM-001', 20, NULL, 110, 2200 UNION ALL
SELECT '1/4/2014'::date, 'ITEM-001', NULL, 4, 200, 800 UNION ALL
SELECT '1/5/2014'::date, 'ITEM-001', 20, NULL, 80, 1600;
Table
SELECT * FROM INVENTORY;
INVENTORY_DATE    ITEM_NAME    PURCHASED_QUANTITY    SOLD QUANTITY     AMOUNT    TOTAL
-----------------------------------------------------------------------------------------
1/1/2014          ITEM-001     10                                      $100      $1000
1/2/2014          ITEM-001                           2                 $200      $400
1/3/2014          ITEM-001     20                                      $110      $2200
1/4/2014          ITEM-001                           4                 $200      $800
1/5/2014          ITEM-001     20                                      $80       $1600
I am trying to create a function like this:
CREATE FUNCTION GET_FIFO_COGS(ITEM_NAME TEXT, QUANTITY INTEGER)
RETURNS MONEY
AS
$$
BEGIN
END
$$
LANGUAGE "PLPGSQL";
So that, I could :
SELECT * FROM GET_FIFO_COGS('ITEM-001', 4) --> $400
--Remaining 4. Each for $100.
SELECT * FROM GET_FIFO_COGS('ITEM-001', 12) --> $1280
--4 for $100, 8 for 110.
SELECT * FROM GET_FIFO_COGS('ITEM-001', 34) --> $3400
--4 for $100, 20 for $110, 10 for $80.
I can improve this question if pointed into the right direction. I am learning SQL, this one is giving me troubles and I am unable to solve this problem because I find it quite tricky for me.
                        
SQL Fiddle
The approach in this solution is to expand each row with
nitems tonrows with a single item usinggenerate_series. Then building two separate sets forpurchasedandsold. Each set's rows are numbered in theinventory_idorder so it is possible to eliminate thepurchaseditems that have already beensold. Thenorder bytheinventory_idandlimitto the quantity.Use it as
Or just