Login     Register

        Contact Us     Search

XLeratorDB/financial Documentation

FIFOdet


FIFOdet
Updated: 13 Jul 2023

Use the SQL Server table-valued function FIFOdet to calculate FIFO (First In, First Out) values in an ordered resultant table. FIFOdet calculates balances for each value from the first value to the last value in the ordered group or partition. FIFOdet returns:

  • the transaction identifier,
  • output row number,
  • transaction quantity,
  • transaction unit price,
  • transaction extended price,
  • inventory on hand including the current transaction,
  • inventory cost including the current transaction,
  • cost of goods sold,
  • gross margin on sale,
  • the transaction identifier of the purchase from which the sale transaction was filled,
  • the quantity from the purchase transaction identifier, and
  • the unit price from the purchase transaction identifier.

FIFOdet assumes that the quantity i.e., the number of units, of the transaction and the monetary value of the transaction have the same sign. Purchase, or additions to inventory, are positive and sales, or withdrawals from inventory, are negative.

FIFOdet will match the first sale transaction with the first purchase transaction. If the sale quantity is less than the purchased quantity, then the remaining balance on the purchase transaction will be applied to the next sale transaction. If the sale quantity is greater than the purchased quantity then FIFOdet will get the next purchase transaction, repeating this process until the remaining balance on the sales transaction is zero or there is no more inventory.

In the event that amount sold is greater than the amount purchased, then the inventory on hand will continue to be updated, but the inventory cost will be zero.

Syntax
SELECT * FROM [wct].[FIFOdet] (
   <@DataQuery, nvarchar(max),>)
Arguments
Input NameDescription
@DataQueryAn SQL statement which returns a resultant table containing the unique transaction identifier, quantity and amount.
Return Type
RETURNS  TABLE (
   [ID] [sql_variant] NULL,
   [RN] [int] NULL,
   [QTY] [float] NULL,
   [UNITPRICE] [float] NULL,
   [EXPRICE] [float] NULL,
   [INVONHAND] [float] NULL,
   [INVCOST] [float] NULL,
   [COGS] [float] NULL,
   [GM] [float] NULL,
   [PURID] [sql_variant] NULL,
   [PURQTY] [float] NULL,
   [PURPRICE] [float] NULL
)
ColumnDescription
IDunique transaction identifier
RNoutput row number
QTYtransaction quantity
UNITPRICEtransaction unit price
EXPRICEtransaction extended price
INVONHANDthe sum of QTY for the current and all preceding rows
INVCOSTthe inventory cost from the preceding row plus the costs of good sold from the current row
COGSthe cost of goods sold for the current row
GMthe gross margin on sales for the current row
PURIDthe transaction identifier of the purchase transaction used in the calculation of the cost of goods sold
PURQTYthe quantity used from purchase transaction
PURPRICEThe unit price from the purchase transaction
Remarks
  • For purchase transactions i.e., where QTY > 0, COGS, GM, PURID, PURQTY and PURPRICE will be NULL.
  • If INVONHAND <= 0 then INVCOST = 0.
  • The number of rows returned by the function may be greater than the number of input rows. The RN column in the resultant table should be used in your SQL to return the output rows in the order in which they were processed by the function.
Examples
Example #1

This is a very simple example showing the movements for one product over the month of June. Since it only involves one product, there is no product identifier in the SQL. The input had been put in date order and then in quantity descending order within date.

SET NOCOUNT ON; 
 
DROP TABLE IF EXISTS #t; --SQL Server 2016 and above 
SELECT 
INTO 
#t 
FROM (VALUES 
 ('20230615001','2023-06-15',-411,11.86) 
,('20230625002','2023-06-25',-921,11.9) 
,('20230628003','2023-06-28',-178,11.77) 
,('20230622004','2023-06-22',742,10.75) 
,('20230629005','2023-06-29',-537,11.91) 
,('20230627006','2023-06-27',639,10.59) 
,('20230606007','2023-06-06',199,10.71) 
,('20230607008','2023-06-07',-215,11.9) 
,('20230623009','2023-06-23',-540,11.95) 
,('20230615010','2023-06-15',699,10.64) 
,('20230630011','2023-06-30',478,10.64) 
,('20230605012','2023-06-05',658,10.65) 
,('20230612013','2023-06-12',-974,11.87) 
,('20230603014','2023-06-03',-704,11.96) 
,('20230603015','2023-06-03',-497,11.89) 
,('20230606016','2023-06-06',231,10.52) 
,('20230627017','2023-06-27',96,10.73) 
,('20230604018','2023-06-04',860,10.51) 
,('20230624019','2023-06-24',-323,11.94) 
,('20230606020','2023-06-06',762,10.7) 
,('20230624021','2023-06-24',-211,11.8) 
,('20230628022','2023-06-28',-195,11.8) 
,('20230617023','2023-06-17',480,10.75) 
,('20230629024','2023-06-29',-950,12) 
,('20230621025','2023-06-21',703,10.72) 
,('20230629026','2023-06-29',551,10.7) 
,('20230628027','2023-06-28',-631,11.81) 
,('20230608028','2023-06-08',448,10.7) 
,('20230613029','2023-06-13',-909,11.97) 
,('20230621030','2023-06-21',762,10.56) 
)n(ordno,orddate,qty,price) 
 
SELECT 
 CAST(k.ID as CHAR(13)) as ID 
,t.orddate as orddate 
,ROUND(k.QTY, 4) as QTY   
,ROUND(k.UNITPRICE, 4) as UNITPRICE 
,ROUND(k.EXPRICE, 4) as EXPRICE               
,ROUND(k.INVONHAND, 4) as INVONHAND                 
,ROUND(k.INVCOST, 4) as INVCOST                    
,ROUND(k.COGS, 4) as COGS                      
,ROUND(k.GM, 4) as GM  
,CAST(k.PURID as CHAR(13)) as PURID 
,ROUND(k.PURQTY, 4) as PURQTY 
,ROUND(k.PURPRICE, 4) as PURPRICE 
FROM 
wct.FIFOdet('SELECT ordno, qty, qty * price FROM #t ORDER BY ORDDATE ASC, qty DESC')k 
INNER JOIN 
#t t 
ON 
k.ID = t.ordno  
ORDER BY 
k.RN  

This produces the following result.

Note that there were 30 input rows and 44 output rows. You should also make note of the fact that the first purchase transaction occurs after the first sale transaction.

Example #2

In this example, we calculate the FIFO balances for multiple products. Doing so requires the use of a CROSS APPLY. In addition to the CROSS APPLY we JOIN to the source table to include the product identifier (and any other data that might be of interest) in the resultant table.

SET NOCOUNT ON;
 
DROP TABLE IF EXISTS #t;    --SQL Server 2016 and above
 
SELECT
    *
INTO
    #t
FROM (VALUES
     ('5FCDA993-9C22-5B41-95DD-58993D627827','20230601001','2023-06-01',-791,11.81)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230619002','2023-06-19',-914,11.8)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230603003','2023-06-03',-728,11.8)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230612004','2023-06-12',-792,11.93)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230611005','2023-06-11',-926,11.85)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230614006','2023-06-14',295,10.75)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230619007','2023-06-19',-13,11.86)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230604008','2023-06-04',435,10.55)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230616009','2023-06-16',314,10.72)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230605010','2023-06-05',72,10.62)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230614011','2023-06-14',271,10.72)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230610012','2023-06-10',486,10.51)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230608013','2023-06-08',394,10.56)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230630014','2023-06-30',634,10.71)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230616015','2023-06-16',-201,11.92)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230622016','2023-06-22',646,10.75)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230601017','2023-06-01',139,10.62)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230626018','2023-06-26',-892,11.77)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230604019','2023-06-04',925,10.56)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230621020','2023-06-21',87,10.74)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230625021','2023-06-25',-560,12)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230601022','2023-06-01',-124,11.99)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230601023','2023-06-01',-760,11.86)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230619024','2023-06-19',664,10.56)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230602025','2023-06-02',-527,11.78)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230623026','2023-06-23',-749,11.79)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230617027','2023-06-17',724,10.72)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230629028','2023-06-29',-691,11.86)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230608029','2023-06-08',124,10.59)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230613030','2023-06-13',-970,11.86)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230615032','2023-06-15',-225,119.08)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230627033','2023-06-27',453,107.14)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230625034','2023-06-25',-475,118.07)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230613035','2023-06-13',-443,118.19)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230620036','2023-06-20',-480,118.63)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230618037','2023-06-18',-352,118.84)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230603038','2023-06-03',345,106.01)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230623039','2023-06-23',-126,118.62)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230610040','2023-06-10',317,107.23)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230603041','2023-06-03',265,105.35)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230615042','2023-06-15',-278,119.92)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230623043','2023-06-23',44,105.1)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230619044','2023-06-19',429,105.14)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230614045','2023-06-14',-419,119.83)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230606046','2023-06-06',100,107.35)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230615047','2023-06-15',358,105.51)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230601048','2023-06-01',351,106.45)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230624049','2023-06-24',-26,119.94)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230615050','2023-06-15',25,106.49)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230629051','2023-06-29',352,106.48)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230611052','2023-06-11',238,106.6)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230630053','2023-06-30',144,107.36)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230602054','2023-06-02',316,105.77)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230606055','2023-06-06',48,107.02)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230624056','2023-06-24',398,106.14)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230627057','2023-06-27',279,106.63)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230616058','2023-06-16',-427,117.55)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230624059','2023-06-24',375,106.75)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230630060','2023-06-30',17,105.13)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230601061','2023-06-01',-92,119.49)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230630063','2023-06-30',-122,10.53)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230604064','2023-06-04',153,11.86)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230629065','2023-06-29',183,12)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230620066','2023-06-20',-144,10.65)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230607067','2023-06-07',-36,10.51)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230603068','2023-06-03',70,11.93)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230616069','2023-06-16',-136,10.73)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230608070','2023-06-08',171,11.86)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230608071','2023-06-08',166,11.75)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230629072','2023-06-29',0,10.74)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230622073','2023-06-22',79,11.86)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230605074','2023-06-05',-115,10.52)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230617075','2023-06-17',-112,10.58)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230606076','2023-06-06',182,11.93)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230630077','2023-06-30',29,11.99)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230602078','2023-06-02',6,11.78)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230620079','2023-06-20',-51,10.51)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230619080','2023-06-19',-107,10.57)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230618081','2023-06-18',-110,10.66)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230629082','2023-06-29',198,11.84)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230607083','2023-06-07',-48,10.61)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230627084','2023-06-27',-118,10.56)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230612085','2023-06-12',35,11.87)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230622086','2023-06-22',76,11.93)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230617087','2023-06-17',-63,10.58)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230621088','2023-06-21',33,12)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230605089','2023-06-05',-23,10.71)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230617090','2023-06-17',19,11.9)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230622091','2023-06-22',121,11.84)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230629092','2023-06-29',172,11.96)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230624094','2023-06-24',-41,106.62)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230622095','2023-06-22',-19,107.12)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230619096','2023-06-19',23,119.33)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230630097','2023-06-30',62,119.9)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230618098','2023-06-18',52,119.01)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230618099','2023-06-18',-70,105.3)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230607100','2023-06-07',47,118.46)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230613101','2023-06-13',-13,105.71)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230622102','2023-06-22',-99,105.99)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230608103','2023-06-08',8,118.3)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230619104','2023-06-19',22,118.98)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230629105','2023-06-29',88,118.06)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230616106','2023-06-16',-8,106.11)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230612107','2023-06-12',92,117.63)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230607108','2023-06-07',-37,106.05)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230603109','2023-06-03',85,118.03)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230605110','2023-06-05',41,119.04)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230628111','2023-06-28',-22,107.41)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230617112','2023-06-17',-91,105.54)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230605113','2023-06-05',-20,106.43)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230612114','2023-06-12',-39,107.2)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230629115','2023-06-29',37,117.58)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230605116','2023-06-05',15,117.66)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230630117','2023-06-30',43,117.65)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230611118','2023-06-11',-33,106.14)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230624119','2023-06-24',-47,105.1)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230614120','2023-06-14',-17,105.41)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230602121','2023-06-02',-93,107.36)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230621122','2023-06-21',-90,105.91)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230612123','2023-06-12',18,119.58)
    )n(id_item,ordno,orddate,qty,price)
 
SELECT
     a.id_item
    ,CAST(k.ID as CHAR(36)) as ID
    ,t.orddate as orddate
    ,ROUND(k.QTY, 4) as QTY  
    ,ROUND(k.UNITPRICE, 4) as UNITPRICE
    ,ROUND(k.EXPRICE, 4) as EXPRICE              
    ,ROUND(k.INVONHAND, 4) as INVONHAND                
    ,ROUND(k.INVCOST, 4) as INVCOST                  
    ,ROUND(k.COGS, 4) as COGS                    
    ,ROUND(k.GM, 4) as GM
    ,CAST(k.PURID as CHAR(36)) as PURID 
    ,ROUND(k.PURQTY, 4) as PURQTY
    ,ROUND(k.PURPRICE, 4) as PURPRICE
FROM
    (SELECT DISTINCT id_item FROM #t)a
CROSS APPLY
    wct.FIFOdet('SELECT ordno, qty, qty * price FROM #t WHERE id_item = ''' + a.id_item +     ''' ORDER BY ORDDATE ASC, qty DESC')k
INNER JOIN
    #t t
ON
    k.ID = t.ordno   
ORDER BY
     a.id_item
    ,k.RN

This produces the following result.

Example #3

In this example, there is a separate table (#i) for all the inventory items and a table for the transactions (#t). This SQL will calculate the FIFO values without having to get the distinct product identifiers from the transaction table.

SET NOCOUNT ON;
 
DROP TABLE IF EXISTS #t;    --SQL Server 2016 and above
DROP TABLE IF EXISTS #i;    --SQL Server 2016 and above
 
SELECT
    *
INTO
    #i
FROM (VALUES
     ('24202201-1770-0D9D-3543-CD78799A9415')
    ,('5FCDA993-9C22-5B41-95DD-58993D627827')
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55')
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF')
    ,('C85837C2-69EF-5A55-0BF3-8D48269B237D')
    ,('388E9D84-6256-0E51-8DA1-0923AA739232')
    ,('4C54AC48-2109-3E57-2D65-EA43A2B64FFE')
    ,('BF97105A-35FA-7E42-6F30-A3C908A12203')
    )n(id)
SELECT
    *
INTO
    #t
FROM (VALUES
     ('5FCDA993-9C22-5B41-95DD-58993D627827','20230601001','2023-06-01',-791,11.81)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230619002','2023-06-19',-914,11.8)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230603003','2023-06-03',-728,11.8)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230612004','2023-06-12',-792,11.93)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230611005','2023-06-11',-926,11.85)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230614006','2023-06-14',295,10.75)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230619007','2023-06-19',-13,11.86)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230604008','2023-06-04',435,10.55)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230616009','2023-06-16',314,10.72)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230605010','2023-06-05',72,10.62)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230614011','2023-06-14',271,10.72)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230610012','2023-06-10',486,10.51)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230608013','2023-06-08',394,10.56)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230630014','2023-06-30',634,10.71)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230616015','2023-06-16',-201,11.92)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230622016','2023-06-22',646,10.75)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230601017','2023-06-01',139,10.62)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230626018','2023-06-26',-892,11.77)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230604019','2023-06-04',925,10.56)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230621020','2023-06-21',87,10.74)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230625021','2023-06-25',-560,12)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230601022','2023-06-01',-124,11.99)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230601023','2023-06-01',-760,11.86)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230619024','2023-06-19',664,10.56)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230602025','2023-06-02',-527,11.78)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230623026','2023-06-23',-749,11.79)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230617027','2023-06-17',724,10.72)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230629028','2023-06-29',-691,11.86)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230608029','2023-06-08',124,10.59)
    ,('5FCDA993-9C22-5B41-95DD-58993D627827','20230613030','2023-06-13',-970,11.86)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230615032','2023-06-15',-225,119.08)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230627033','2023-06-27',453,107.14)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230625034','2023-06-25',-475,118.07)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230613035','2023-06-13',-443,118.19)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230620036','2023-06-20',-480,118.63)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230618037','2023-06-18',-352,118.84)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230603038','2023-06-03',345,106.01)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230623039','2023-06-23',-126,118.62)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230610040','2023-06-10',317,107.23)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230603041','2023-06-03',265,105.35)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230615042','2023-06-15',-278,119.92)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230623043','2023-06-23',44,105.1)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230619044','2023-06-19',429,105.14)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230614045','2023-06-14',-419,119.83)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230606046','2023-06-06',100,107.35)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230615047','2023-06-15',358,105.51)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230601048','2023-06-01',351,106.45)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230624049','2023-06-24',-26,119.94)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230615050','2023-06-15',25,106.49)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230629051','2023-06-29',352,106.48)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230611052','2023-06-11',238,106.6)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230630053','2023-06-30',144,107.36)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230602054','2023-06-02',316,105.77)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230606055','2023-06-06',48,107.02)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230624056','2023-06-24',398,106.14)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230627057','2023-06-27',279,106.63)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230616058','2023-06-16',-427,117.55)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230624059','2023-06-24',375,106.75)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230630060','2023-06-30',17,105.13)
    ,('E412D80E-6993-43D8-38BB-E61EAFD158FF','20230601061','2023-06-01',-92,119.49)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230630063','2023-06-30',-122,10.53)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230604064','2023-06-04',153,11.86)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230629065','2023-06-29',183,12)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230620066','2023-06-20',-144,10.65)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230607067','2023-06-07',-36,10.51)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230603068','2023-06-03',70,11.93)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230616069','2023-06-16',-136,10.73)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230608070','2023-06-08',171,11.86)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230608071','2023-06-08',166,11.75)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230629072','2023-06-29',0,10.74)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230622073','2023-06-22',79,11.86)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230605074','2023-06-05',-115,10.52)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230617075','2023-06-17',-112,10.58)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230606076','2023-06-06',182,11.93)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230630077','2023-06-30',29,11.99)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230602078','2023-06-02',6,11.78)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230620079','2023-06-20',-51,10.51)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230619080','2023-06-19',-107,10.57)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230618081','2023-06-18',-110,10.66)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230629082','2023-06-29',198,11.84)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230607083','2023-06-07',-48,10.61)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230627084','2023-06-27',-118,10.56)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230612085','2023-06-12',35,11.87)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230622086','2023-06-22',76,11.93)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230617087','2023-06-17',-63,10.58)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230621088','2023-06-21',33,12)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230605089','2023-06-05',-23,10.71)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230617090','2023-06-17',19,11.9)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230622091','2023-06-22',121,11.84)
    ,('E3FDD639-540F-0CE1-4C04-ED48E7F44D55','20230629092','2023-06-29',172,11.96)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230624094','2023-06-24',-41,106.62)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230622095','2023-06-22',-19,107.12)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230619096','2023-06-19',23,119.33)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230630097','2023-06-30',62,119.9)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230618098','2023-06-18',52,119.01)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230618099','2023-06-18',-70,105.3)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230607100','2023-06-07',47,118.46)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230613101','2023-06-13',-13,105.71)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230622102','2023-06-22',-99,105.99)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230608103','2023-06-08',8,118.3)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230619104','2023-06-19',22,118.98)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230629105','2023-06-29',88,118.06)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230616106','2023-06-16',-8,106.11)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230612107','2023-06-12',92,117.63)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230607108','2023-06-07',-37,106.05)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230603109','2023-06-03',85,118.03)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230605110','2023-06-05',41,119.04)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230628111','2023-06-28',-22,107.41)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230617112','2023-06-17',-91,105.54)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230605113','2023-06-05',-20,106.43)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230612114','2023-06-12',-39,107.2)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230629115','2023-06-29',37,117.58)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230605116','2023-06-05',15,117.66)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230630117','2023-06-30',43,117.65)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230611118','2023-06-11',-33,106.14)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230624119','2023-06-24',-47,105.1)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230614120','2023-06-14',-17,105.41)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230602121','2023-06-02',-93,107.36)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230621122','2023-06-21',-90,105.91)
    ,('24202201-1770-0D9D-3543-CD78799A9415','20230612123','2023-06-12',18,119.58)
    )n(id_item,ordno,orddate,qty,price)
SELECT
     a.id_item
    ,CAST(k.ID as CHAR(11)) as ID
    ,t.orddate as orddate
    ,ROUND(k.QTY, 4) as QTY  
    ,ROUND(k.UNITPRICE, 4) as UNITPRICE
    ,ROUND(k.EXPRICE, 4) as EXPRICE              
    ,ROUND(k.INVONHAND, 4) as INVONHAND                
    ,ROUND(k.INVCOST, 4) as INVCOST                  
    ,ROUND(k.COGS, 4) as COGS                    
    ,ROUND(k.GM, 4) as GM
    ,CAST(k.PURID as CHAR(36)) as PURID
    ,ROUND(k.PURQTY, 4) as PURQTY
    ,ROUND(k.PURPRICE, 4) as PURPRICE
FROM
    (SELECT id as id_item FROM #i)a
CROSS APPLY
    wct.FIFOdet('SELECT ordno, qty, qty * price FROM #t WHERE id_item = ''' + a.id_item +     ''' ORDER BY ORDDATE ASC, qty DESC')k
INNER JOIN
    #t t
ON
    k.ID = t.ordno   
ORDER BY
     a.id_item
    ,k.RN

This produces the following result.

Example #4

In this example we show how to get the ending inventories balances. We put some transaction date in #t and then use FIFOdet to put the inventory calculations in #fifo. We then execute SQL to get the ending inventory on hand and the cost of that inventory for each product in #fifo.

SET NOCOUNT ON;
 
DROP TABLE IF EXISTS #t;        --SQL Server 2016 and above
DROP TABLE IF EXISTS #fifo;        --SQL Server 2016 and above
 
--Put some data in #t
SELECT
    *
INTO
    #t
FROM
    (VALUES
     ('2020-11-18-002','PROD-000174','2020-11-18',223.18,921.06,205562.1708)
    ,('2022-04-15-009','PROD-000536','2022-04-15',187.13,73.54,13761.5402)
    ,('2022-04-17-002','PROD-000790','2022-04-17',50.43,307.51,15507.7293)
    ,('2020-09-03-007','PROD-000174','2020-09-03',235.1,570.99,134239.749)
    ,('2020-09-03-008','PROD-000536','2020-09-03',4.47,101.87,455.3589)
    ,('2021-05-19-001','PROD-000536','2021-05-19',-22.05,603.67,-13310.9235)
    ,('2021-12-05-008','PROD-001503','2021-12-05',-12.8,1449.14,-18548.992)
    ,('2022-03-30-003','PROD-000790','2022-03-30',-457.17,327.93,-149919.7581)
    ,('2022-07-18-008','PROD-000790','2022-07-18',-440.99,239.53,-105630.3347)
    ,('2022-07-18-010','PROD-000536','2022-07-18',-21.18,466.12,-9872.4216)
    ,('2020-12-29-008','PROD-000174','2020-12-29',-258.02,896.95,-231431.039)
    ,('2021-12-18-006','PROD-001503','2021-12-18',-62.66,119.22,-7470.3252)
    ,('2022-02-11-001','PROD-000174','2022-02-11',183.58,861.8,158209.244)
    ,('2022-02-12-004','PROD-000174','2022-02-12',251.96,751.35,189310.146)
    ,('2022-05-05-004','PROD-001503','2022-05-05',-44.83,464,-20801.12)
    ,('2023-05-23-001','PROD-000790','2023-05-23',-305.53,386.39,-118053.7367)
    ,('2020-07-17-003','PROD-000174','2020-07-17',-94.4,529.46,-49981.024)
    ,('2021-11-16-009','PROD-001503','2021-11-16',-34.56,1664.7,-57532.032)
    ,('2021-11-17-005','PROD-001503','2021-11-17',-49.98,1406.02,-70272.8796)
    ,('2021-11-19-007','PROD-001503','2021-11-19',-66.05,64.29,-4246.3545)
    ,('2022-03-08-007','PROD-000536','2022-03-08',28.94,69.75,2018.565)
    ,('2022-03-15-002','PROD-000536','2022-03-15',-1.98,570.72,-1130.0256)
    ,('2022-06-08-002','PROD-001503','2022-06-08',-20.28,305.35,-6192.498)
    ,('2022-06-13-003','PROD-000536','2022-06-13',128.65,46.35,5962.9275)
    ,('2021-08-08-004','PROD-000536','2021-08-08',152.55,85.52,13046.076)
    ,('2022-05-27-001','PROD-001503','2022-05-27',-11.62,1877.09,-21811.7858)
    ,('2022-08-25-006','PROD-000790','2022-08-25',-179.22,233.08,-41772.5976)
    ,('2021-05-20-005','PROD-000174','2021-05-20',507.47,808.33,410203.2251)
    ,('2021-11-03-003','PROD-001503','2021-11-03',-17.99,154.53,-2779.9947)
    ,('2022-10-24-004','PROD-000790','2022-10-24',-133.09,507.95,-67603.0655)
    ,('2023-04-25-004','PROD-000858','2023-04-25',-102.2,64.95,-6637.89)
    ,('2023-06-02-005','PROD-000858','2023-06-02',78.06,572.11,44658.9066)
    ,('2023-06-03-002','PROD-000858','2023-06-03',488.89,589.58,288239.7662)
    ,('2023-06-04-010','PROD-000858','2023-06-04',361.51,450.95,163022.9345)
    ,('2023-06-07-001','PROD-000858','2023-06-07',796.21,554.68,441641.7628)
    ,('2023-06-10-006','PROD-000858','2023-06-10',578.43,947.96,548328.5028)
    ,('2023-06-11-007','PROD-000858','2023-06-11',-92.17,60.94,-5616.8398)
    ,('2023-06-15-008','PROD-000858','2023-06-15',97.65,709.47,69279.7455)
    ,('2020-10-26-005','PROD-000536','2020-10-26',132.16,140.27,18538.0832)
    ,('2021-01-13-006','PROD-000174','2021-01-13',434.12,967.74,420115.2888)
    ,('2021-07-25-009','PROD-000174','2021-07-25',-308.81,1262.86,-389983.7966)
    ,('2021-10-06-010','PROD-001503','2021-10-06',-69.61,584.84,-40710.7124)
    ,('2022-05-20-011','PROD-001503','2022-05-20',-33.21,648.4,-21533.364)
    ,('2023-02-20-007','PROD-000790','2023-02-20',-629.76,340.04,-214143.5904)
    ,('2023-02-26-010','PROD-000790','2023-02-26',-640.88,648.62,-415687.5856)
    ,('2023-06-17-003','PROD-000858','2023-06-17',304.03,728.47,221476.7341)
    ,('2023-06-17-009','PROD-000858','2023-06-17',712.42,588.63,419351.7846)
    ,('2022-03-25-006','PROD-000536','2022-03-25',148.11,84.54,12521.2194)
    ,('2022-12-05-009','PROD-000790','2022-12-05',-280.92,305,-85680.6)
    ,('2023-04-01-005','PROD-000790','2023-04-01',-32.38,409.86,-13271.2668)
    )n(trn,prod,tdate,qty,unitprice,extprice);
--Run FIFOdet and store the results in #fifo   
SELECT
     CAST(n.prod as varchar(11)) as prod
    ,k.rn
    ,CAST(k.ID as varchar(14)) as ID
    ,ROUND(k.qty, 4) as qty
    ,ROUND(k.unitprice, 4) as unitprice
    ,ROUND(k.EXPRICE, 4) as exprice
    ,ROUND(k.INVONHAND, 4) as invonhand
    ,ROUND(k.INVCOST, 4) as invcost
    ,ROUND(k.COGS, 4) as cogs
    ,ROUND(k.GM, 4) as gm
    ,CAST(k.PURID as varchar(14)) as purid
    ,ROUND(k.PURQTY, 4) as purqty
    ,ROUND(k.PURPRICE, 4) purprice
INTO
    #fifo
FROM
    (SELECT DISTINCT PROD FROM #t)n
CROSS APPLY
    wct.FIFOdet(REPLACE('SELECT trn,qty,extprice FROM #t WHERE prod = ''@prod'' ORDER BY     tdate ASC, qty DESC','@prod',n.prod))k
 
--Get the closing balances
SELECT
     prod
    ,invonhand
    ,invcost
FROM
    (
    SELECT
         ROW_NUMBER() OVER (PARTITION BY PROD ORDER BY PROD, RN DESC) as rnrev
        ,f.*
    FROM
        #fifo f
    )n
WHERE
    rnrev = 1

This produces the following result.

Note that 2 of the products have negative inventory balances, meaning that the sales exceeded the purchases. Since the inventory balance is less than zero the inventory cost is zero. In the next two examples we will show how to get the details for inventory balances greater than zero and less than zero.

Example #5

In this example, using the same tables that were created in Example #4, we show how to get the details of the outstanding inventory balances i.e., positive balances. For this example, those details are the product identifier, the transaction identifier, the transaction date, the original transaction quantity, the remaining transaction quantity, the original transaction amount, and the remaining transaction amount. This information might be used in the next inventory calculation after all the settled transactions have been archived. Additionally, we have included running totals of the inventory quantity and inventory cost which show that the amounts agree with the amounts in Example #4.

SET NOCOUNT ON;
 
DROP TABLE IF EXISTS #t;        --SQL Server 2016 and above
DROP TABLE IF EXISTS #fifo;        --SQL Server 2016 and above
 
--Put some data in #t
SELECT
    *
INTO
    #t
FROM
    (VALUES
     ('2020-11-18-002','PROD-000174','2020-11-18',223.18,921.06,205562.1708)
    ,('2022-04-15-009','PROD-000536','2022-04-15',187.13,73.54,13761.5402)
    ,('2022-04-17-002','PROD-000790','2022-04-17',50.43,307.51,15507.7293)
    ,('2020-09-03-007','PROD-000174','2020-09-03',235.1,570.99,134239.749)
    ,('2020-09-03-008','PROD-000536','2020-09-03',4.47,101.87,455.3589)
    ,('2021-05-19-001','PROD-000536','2021-05-19',-22.05,603.67,-13310.9235)
    ,('2021-12-05-008','PROD-001503','2021-12-05',-12.8,1449.14,-18548.992)
    ,('2022-03-30-003','PROD-000790','2022-03-30',-457.17,327.93,-149919.7581)
    ,('2022-07-18-008','PROD-000790','2022-07-18',-440.99,239.53,-105630.3347)
    ,('2022-07-18-010','PROD-000536','2022-07-18',-21.18,466.12,-9872.4216)
    ,('2020-12-29-008','PROD-000174','2020-12-29',-258.02,896.95,-231431.039)
    ,('2021-12-18-006','PROD-001503','2021-12-18',-62.66,119.22,-7470.3252)
    ,('2022-02-11-001','PROD-000174','2022-02-11',183.58,861.8,158209.244)
    ,('2022-02-12-004','PROD-000174','2022-02-12',251.96,751.35,189310.146)
    ,('2022-05-05-004','PROD-001503','2022-05-05',-44.83,464,-20801.12)
    ,('2023-05-23-001','PROD-000790','2023-05-23',-305.53,386.39,-118053.7367)
    ,('2020-07-17-003','PROD-000174','2020-07-17',-94.4,529.46,-49981.024)
    ,('2021-11-16-009','PROD-001503','2021-11-16',-34.56,1664.7,-57532.032)
    ,('2021-11-17-005','PROD-001503','2021-11-17',-49.98,1406.02,-70272.8796)
    ,('2021-11-19-007','PROD-001503','2021-11-19',-66.05,64.29,-4246.3545)
    ,('2022-03-08-007','PROD-000536','2022-03-08',28.94,69.75,2018.565)
    ,('2022-03-15-002','PROD-000536','2022-03-15',-1.98,570.72,-1130.0256)
    ,('2022-06-08-002','PROD-001503','2022-06-08',-20.28,305.35,-6192.498)
    ,('2022-06-13-003','PROD-000536','2022-06-13',128.65,46.35,5962.9275)
    ,('2021-08-08-004','PROD-000536','2021-08-08',152.55,85.52,13046.076)
    ,('2022-05-27-001','PROD-001503','2022-05-27',-11.62,1877.09,-21811.7858)
    ,('2022-08-25-006','PROD-000790','2022-08-25',-179.22,233.08,-41772.5976)
    ,('2021-05-20-005','PROD-000174','2021-05-20',507.47,808.33,410203.2251)
    ,('2021-11-03-003','PROD-001503','2021-11-03',-17.99,154.53,-2779.9947)
    ,('2022-10-24-004','PROD-000790','2022-10-24',-133.09,507.95,-67603.0655)
    ,('2023-04-25-004','PROD-000858','2023-04-25',-102.2,64.95,-6637.89)
    ,('2023-06-02-005','PROD-000858','2023-06-02',78.06,572.11,44658.9066)
    ,('2023-06-03-002','PROD-000858','2023-06-03',488.89,589.58,288239.7662)
    ,('2023-06-04-010','PROD-000858','2023-06-04',361.51,450.95,163022.9345)
    ,('2023-06-07-001','PROD-000858','2023-06-07',796.21,554.68,441641.7628)
    ,('2023-06-10-006','PROD-000858','2023-06-10',578.43,947.96,548328.5028)
    ,('2023-06-11-007','PROD-000858','2023-06-11',-92.17,60.94,-5616.8398)
    ,('2023-06-15-008','PROD-000858','2023-06-15',97.65,709.47,69279.7455)
    ,('2020-10-26-005','PROD-000536','2020-10-26',132.16,140.27,18538.0832)
    ,('2021-01-13-006','PROD-000174','2021-01-13',434.12,967.74,420115.2888)
    ,('2021-07-25-009','PROD-000174','2021-07-25',-308.81,1262.86,-389983.7966)
    ,('2021-10-06-010','PROD-001503','2021-10-06',-69.61,584.84,-40710.7124)
    ,('2022-05-20-011','PROD-001503','2022-05-20',-33.21,648.4,-21533.364)
    ,('2023-02-20-007','PROD-000790','2023-02-20',-629.76,340.04,-214143.5904)
    ,('2023-02-26-010','PROD-000790','2023-02-26',-640.88,648.62,-415687.5856)
    ,('2023-06-17-003','PROD-000858','2023-06-17',304.03,728.47,221476.7341)
    ,('2023-06-17-009','PROD-000858','2023-06-17',712.42,588.63,419351.7846)
    ,('2022-03-25-006','PROD-000536','2022-03-25',148.11,84.54,12521.2194)
    ,('2022-12-05-009','PROD-000790','2022-12-05',-280.92,305,-85680.6)
    ,('2023-04-01-005','PROD-000790','2023-04-01',-32.38,409.86,-13271.2668)
    )n(trn,prod,tdate,qty,unitprice,extprice);
 
--Run FIFOdet and store the results in #fifo   
SELECT
     CAST(n.prod as varchar(11)) as prod
    ,k.rn
    ,CAST(k.ID as varchar(14)) as ID
    ,ROUND(k.qty, 4) as qty
    ,ROUND(k.unitprice, 4) as unitprice
    ,ROUND(k.EXPRICE, 4) as exprice
    ,ROUND(k.INVONHAND, 4) as invonhand
    ,ROUND(k.INVCOST, 4) as invcost
    ,ROUND(k.COGS, 4) as cogs
    ,ROUND(k.GM, 4) as gm
    ,CAST(k.PURID as varchar(14)) as purid
    ,ROUND(k.PURQTY, 4) as purqty
    ,ROUND(k.PURPRICE, 4) purprice
INTO
    #fifo
FROM
    (SELECT DISTINCT PROD FROM #t)n
CROSS APPLY
    wct.FIFOdet(REPLACE('SELECT trn,qty,extprice FROM #t WHERE prod = ''@prod'' ORDER BY tdate ASC, qty DESC','@prod',n.prod))k
 
--Get the closing balances
SELECT
     prod
    ,invonhand
    ,invcost
FROM
    (
    SELECT
         ROW_NUMBER() OVER (PARTITION BY PROD ORDER BY PROD, RN DESC) as rnrev
        ,f.*
    FROM
        #fifo f
    )n
WHERE
    rnrev = 1
 
--Get the details for the closing inventory
SELECT
    n.PROD,
    n.ID,
    t.tdate,
    t.qty as [Original Transaction Quantity],
    INVONHAND as [Remaining Transaction Quantity],
    t.extprice as [Original Transaction Cost],
    INVCOST as [Remaining Transaction Cost],
    SUM(INVONHAND) OVER (PARTITION BY n.PROD ORDER BY n.PROD, t.tdate ASC, t.qty DESC) as [Running Inventory Quantity],
    SUM(INVCOST) OVER (PARTITION BY n.PROD ORDER BY n.PROD, t.tdate ASC, t.qty DESC) as [Running Inventory Cost]
FROM (
    SELECT
        p.PROD,
        p.ID,
        ROUND(p.qty+SUM(ISNULL(-s.PURQTY, 0)),4) AS INVONHAND,
        ROUND(p.exprice+SUM(ISNULL(s.COGS,0)), 4) AS INVCOST
    FROM
        #fifo p
    LEFT OUTER JOIN
        #fifo s
    ON
        p.PROD = s.prod
        AND p.id = s.purid
    WHERE
        p.qty > 0
    GROUP BY
        p.PROD,
        p.ID,
        p.qty,
        p.exprice
    )n
INNER JOIN
    #t t
ON
    n.ID = t.trn
WHERE
    INVONHAND > 0
ORDER BY
    n.prod,
    t.tdate ASC,
    t.qty DESC

This produces the following result.

Example #6

In this example, using the same tables that were created in Example #4, we show how to get the details of the outstanding unfilled order balances i.e., negative balances. For this example, those details are the product identifier, the transaction identifier, the transaction date, the original transaction quantity, the remaining transaction quantity, the original transaction amount, and the remaining transaction amount. This information might be used in the next inventory calculation after all the settled transactions have been archived. Additionally, we have included running totals of the sale quantity and sale amount which show that the amounts agree with the amounts in Example #4.

SET NOCOUNT ON;
 
DROP TABLE IF EXISTS #t;        --SQL Server 2016 and above
DROP TABLE IF EXISTS #fifo;        --SQL Server 2016 and above
 
--Put some data in #t
SELECT
    *
INTO
    #t
FROM
    (VALUES
     ('2020-11-18-002','PROD-000174','2020-11-18',223.18,921.06,205562.1708)
    ,('2022-04-15-009','PROD-000536','2022-04-15',187.13,73.54,13761.5402)
    ,('2022-04-17-002','PROD-000790','2022-04-17',50.43,307.51,15507.7293)
    ,('2020-09-03-007','PROD-000174','2020-09-03',235.1,570.99,134239.749)
    ,('2020-09-03-008','PROD-000536','2020-09-03',4.47,101.87,455.3589)
    ,('2021-05-19-001','PROD-000536','2021-05-19',-22.05,603.67,-13310.9235)
    ,('2021-12-05-008','PROD-001503','2021-12-05',-12.8,1449.14,-18548.992)
    ,('2022-03-30-003','PROD-000790','2022-03-30',-457.17,327.93,-149919.7581)
    ,('2022-07-18-008','PROD-000790','2022-07-18',-440.99,239.53,-105630.3347)
    ,('2022-07-18-010','PROD-000536','2022-07-18',-21.18,466.12,-9872.4216)
    ,('2020-12-29-008','PROD-000174','2020-12-29',-258.02,896.95,-231431.039)
    ,('2021-12-18-006','PROD-001503','2021-12-18',-62.66,119.22,-7470.3252)
    ,('2022-02-11-001','PROD-000174','2022-02-11',183.58,861.8,158209.244)
    ,('2022-02-12-004','PROD-000174','2022-02-12',251.96,751.35,189310.146)
    ,('2022-05-05-004','PROD-001503','2022-05-05',-44.83,464,-20801.12)
    ,('2023-05-23-001','PROD-000790','2023-05-23',-305.53,386.39,-118053.7367)
    ,('2020-07-17-003','PROD-000174','2020-07-17',-94.4,529.46,-49981.024)
    ,('2021-11-16-009','PROD-001503','2021-11-16',-34.56,1664.7,-57532.032)
    ,('2021-11-17-005','PROD-001503','2021-11-17',-49.98,1406.02,-70272.8796)
    ,('2021-11-19-007','PROD-001503','2021-11-19',-66.05,64.29,-4246.3545)
    ,('2022-03-08-007','PROD-000536','2022-03-08',28.94,69.75,2018.565)
    ,('2022-03-15-002','PROD-000536','2022-03-15',-1.98,570.72,-1130.0256)
    ,('2022-06-08-002','PROD-001503','2022-06-08',-20.28,305.35,-6192.498)
    ,('2022-06-13-003','PROD-000536','2022-06-13',128.65,46.35,5962.9275)
    ,('2021-08-08-004','PROD-000536','2021-08-08',152.55,85.52,13046.076)
    ,('2022-05-27-001','PROD-001503','2022-05-27',-11.62,1877.09,-21811.7858)
    ,('2022-08-25-006','PROD-000790','2022-08-25',-179.22,233.08,-41772.5976)
    ,('2021-05-20-005','PROD-000174','2021-05-20',507.47,808.33,410203.2251)
    ,('2021-11-03-003','PROD-001503','2021-11-03',-17.99,154.53,-2779.9947)
    ,('2022-10-24-004','PROD-000790','2022-10-24',-133.09,507.95,-67603.0655)
    ,('2023-04-25-004','PROD-000858','2023-04-25',-102.2,64.95,-6637.89)
    ,('2023-06-02-005','PROD-000858','2023-06-02',78.06,572.11,44658.9066)
    ,('2023-06-03-002','PROD-000858','2023-06-03',488.89,589.58,288239.7662)
    ,('2023-06-04-010','PROD-000858','2023-06-04',361.51,450.95,163022.9345)
    ,('2023-06-07-001','PROD-000858','2023-06-07',796.21,554.68,441641.7628)
    ,('2023-06-10-006','PROD-000858','2023-06-10',578.43,947.96,548328.5028)
    ,('2023-06-11-007','PROD-000858','2023-06-11',-92.17,60.94,-5616.8398)
    ,('2023-06-15-008','PROD-000858','2023-06-15',97.65,709.47,69279.7455)
    ,('2020-10-26-005','PROD-000536','2020-10-26',132.16,140.27,18538.0832)
    ,('2021-01-13-006','PROD-000174','2021-01-13',434.12,967.74,420115.2888)
    ,('2021-07-25-009','PROD-000174','2021-07-25',-308.81,1262.86,-389983.7966)
    ,('2021-10-06-010','PROD-001503','2021-10-06',-69.61,584.84,-40710.7124)
    ,('2022-05-20-011','PROD-001503','2022-05-20',-33.21,648.4,-21533.364)
    ,('2023-02-20-007','PROD-000790','2023-02-20',-629.76,340.04,-214143.5904)
    ,('2023-02-26-010','PROD-000790','2023-02-26',-640.88,648.62,-415687.5856)
    ,('2023-06-17-003','PROD-000858','2023-06-17',304.03,728.47,221476.7341)
    ,('2023-06-17-009','PROD-000858','2023-06-17',712.42,588.63,419351.7846)
    ,('2022-03-25-006','PROD-000536','2022-03-25',148.11,84.54,12521.2194)
    ,('2022-12-05-009','PROD-000790','2022-12-05',-280.92,305,-85680.6)
    ,('2023-04-01-005','PROD-000790','2023-04-01',-32.38,409.86,-13271.2668)
    )n(trn,prod,tdate,qty,unitprice,extprice);
 
--Run FIFOdet and store the results in #fifo   
SELECT
     CAST(n.prod as varchar(11)) as prod
    ,k.rn
    ,CAST(k.ID as varchar(14)) as ID
    ,ROUND(k.qty, 4) as qty
    ,ROUND(k.unitprice, 4) as unitprice
    ,ROUND(k.EXPRICE, 4) as exprice
    ,ROUND(k.INVONHAND, 4) as invonhand
    ,ROUND(k.INVCOST, 4) as invcost
    ,ROUND(k.COGS, 4) as cogs
    ,ROUND(k.GM, 4) as gm
    ,CAST(k.PURID as varchar(14)) as purid
    ,ROUND(k.PURQTY, 4) as purqty
    ,ROUND(k.PURPRICE, 4) purprice
INTO
    #fifo
FROM
    (SELECT DISTINCT PROD FROM #t)n
CROSS APPLY
    wct.FIFOdet(REPLACE('SELECT trn,qty,extprice FROM #t WHERE prod = ''@prod'' ORDER BY tdate ASC, qty DESC','@prod',n.prod))k
 
--Get the unfilled sales
SELECT
    f.prod,
    f.ID,
    t.tdate,
    t.qty as [Original Transaction Quantity],
    f.qty as [Remaining Transaction Quantity],
    t.extprice as [Original Transaction Amount],
    f.exprice [Remaining Transaction Amount],
    SUM(f.qty) OVER (PARTITION BY f.prod ORDER BY f.prod, f.rn) as [Running Sale Quantity],
    SUM(f.exprice) OVER (PARTITION BY f.prod ORDER BY f.prod, f.rn) as [Running Sale Amount]
FROM
    #fifo f
null">INNER JOIN
    #t t
ON
    f.ID = t.trn
WHERE
    f.qty < 0
    AND purid IS NULL

This produces the following result.

 

See Also

 



Copyright 2008-2024 Westclintech LLC         Privacy Policy        Terms of Service