先进先出(FIFO)库存成本核算

时间:2012-06-26 09:15:26

标签: sql sql-server-2008

这是一篇有趣的文章,我发现在我的项目中很有用:

Set-based Speed Phreakery: The FIFO Stock Inventory SQL Problem

  

我们用来跟踪库存进出虚拟库存仓库的轨道移动的库存表。我们的仓库最初是空的,然后库存由于库存购买(tranCode ='IN')或由于后续退货(tranCode ='RET')而进入仓库,当库存移出仓库时它被出售(tranCode ='OUT')。每种类型的库存都由ArticleID标识。由于购买,销售或返回给定物品,库存进出仓库的每次移动都会导致一行被添加到Stock表中,由StockID标识列中的值唯一标识,并描述了多少已添加或删除商品,购买价格,交易日期等。

虽然我在正在进行的项目中使用这个,但我坚持如何在每次交易'OUT'上获得价格。我需要有这个价值来确定我会向客户收取多少费用。

  1. 首先在库存中添加5个苹果(每个10.00美元),总计$ 50.00

  2. 将3个苹果(每个20.00美元)添加到8个苹果的库存中,总价格为110.00美元

  3. 然后拿出6件物品(5件每件10.00美元,每件1件20美元)总计70美元

  4. 交易完成后,将分别留下2个苹果@ 20美元,共计40美元


  5.  Here's my current table
     Item    transaction code    qty     price   
     apple   IN                    5     10.00    
     apple   IN                    3     20.00   
     apple   OUT                   6          
    
     Manual computation for the OUT transaction price (FIFO)
     QTY     price   total price 
     5       10.00   50.00 
     1       20.00   20.00 
     TOTAL:6         70.00 
    
     Output of the script:
     Item    CurrentItems   CurrentValue
     apple   2            40.00
    
     What I need:
     Item    transaction code    qty     price   CurrentItems    CurrentValue 
     apple   IN                    5     10.00   5               50.00 
     apple   IN                    3     20.00   8               110.00 
     apple   OUT                   6             2                   40.00 
    
     This too will be OK
     Item    transaction code    qty     price   CurrentItems    
     apple   IN                    5     10.00   0               
     apple   IN                    3     20.00   0                
     apple   OUT                   6         70 
    

    脚本贴出来赢得了比赛是非常有用的,我希望有人能帮助我如何获得每次'OUT'交易的价格

5 个答案:

答案 0 :(得分:1)

我建议您按照以下方式设计表格: 在表格中添加一个新字段,即qty_out

销售前的表格:

Item transaction code    qty     qty_out  price   
 apple   IN                    5    0        10.00    
 apple   IN                    3    0        20.00   
 apple   OUT                   6    null

卖掉这6件物品后的桌子:

Item    transaction code    qty     qty_out  price   
 apple   IN                    5    5        10.00    
 apple   IN                    3    1        20.00   
 apple   OUT                   6    null

您可以将“qty”与“qty_out”(对于IN交易)进行比较,以找出价格。

答案 1 :(得分:0)

如何构建一个每个产品项目有一行的表格,因此每个苹果的行都会插入其价格和可用性(未售出/售出)。
然后,您只需选择前n项,并将价格与您想要的每种产品相关联。基本上,您只是创建一个项目队列,并从队列的前面(具有最早的插入日期)中删除那些“未售出”的项目。

答案 2 :(得分:0)

根据文章,脚本得到的结果是库存的价值。您需要对其进行修改,以便不使用所有库存计算,而只使用前N个项目。

我建议使用CASE语句来设置每个'IN'中的项目数,因为您知道了库存项目和要取出的数量,因此检查了运行总计。

答案 3 :(得分:0)

您无法跟踪每个OUT交易本身,但您可以通过取最后一个(除了您要计算的)IN或OUT行以及它想要计算的当前值列和负当前值来计算它。

在这个例子中

StockID  ArticleID  TranDate  TranCode  Items    Price    CurrentItems  CurrentValue
4567     10000      10:45:07  IN          738   245.94             738    181,503.72
21628    10000      12:05:25  OUT         600                      138     33,939.72
22571    10000      14:39:27  IN           62   199.95             200     46,336.62
30263    10000      16:14:13  OUT         165                       35      6,998.25
42090    10000      18:18:58  RET           5                       40      7,998.00
53143    10000      20:18:54  IN          500   135.91             540     75,953.00
交易30263的价格将是46,336.62 - 6,998.25 = 39,338.37

答案 4 :(得分:0)

请参阅TSQL中的以下代码。基本理念是

  1. 对于每个卖出行,说数量是数量,计算当前行的运行总销售额,称之为Previous_Sold。

  2. 对于步骤1中的每个卖出行,找到所有PREVIOUS买入行,并计算出购买的最高库存量,称之为Previous_Running_Stock。

  3. 在步骤2中购买行,计算

  4. Open_Stock = Previous_Running_Stock - Previous_Sold

    Close_stock = Previous_Running_Stock - Previous_Sold - 数量。

    1. 过滤并仅保留购买行
    2. open_stock> 0,表示有足够的​​库存来填充卖单

      和close_stock< 0表示购买行中的库存全部用完,或者最早(第一行),其中close_stock> = 0,表示部分使用从该行购买。

      1. 汇总(总和产品)价格和数量,以便在第4步获得LIFO成本。
      2. 我相信它很容易修改为LIFO和平均成本。

        --initial table of trades
        item       item_trade_order     direction  unit_price    qty
        Apple      1                    buy        10            100
        Apple      2                    buy        9             150
        Blueberry  1                    buy        5             300   
        Apple      3                    sell       12            50
        Apple      4                    buy        11            200
        Apple      5                    sell       10            350
        Blueberry  2                    sell       10            50
        
        
        --code, using CTE
        
        
        ; with step1 as
        (
            select *
                , coalesce(sum(case direction when 'sell' then 1 else 0 end * qty) over(partition by item order by item_order rows between unbounded preceding and 1 preceding), 0) Previous_Sold
            from trade 
        )
        , step2_3 as
        (
            select *
                , Previous_running_stock - Previous_Sold Open_Stock
                , Previous_running_stock - Previous_Sold - qty Close_Stock
                , ROW_NUMBER() over(partition by item, item_order order by (case when Previous_running_stock - Previous_Sold - qty < 0  then null else 0 - item_order end) desc) rnk
            from step1 t1
            cross apply
            (
                select item_order batch_order, price batch_prc, qty batch_qty
                    , sum(qty) over(order by item_order rows unbounded preceding) Previous_running_stock
                from trade
                where direction = 'buy'
                and item = t1.item
                and item_order < t1.item_order
            ) batch
            where t1.direction = 'sell'
        )
        , step4 as
        (
            select *
            from step2_3
            where Open_Stock > 0
            and (Close_Stock < 0 or rnk = 1)
        )
        select item, item_order, direction, AVG(price) prc, AVG(qty) qty
            ,   sum(case when Close_Stock > 0 then batch_qty - close_stock else case when open_stock < batch_qty then open_stock else batch_qty end end * Batch_Prc) / nullif(avg(qty), 0) FifoUnitCost
        from step4
        group by item, item_order, direction
        order by item, item_order