FIFO Implementation in Inventory using SQL

后端 未结 2 1945
情歌与酒
情歌与酒 2020-12-14 04:41

This is basically an inventory project which tracks the \"Stock In\" and \"Stock Out\" of items through Purchase and sales respectively.

The inventory system follows

相关标签:
2条回答
  • 2020-12-14 04:47

    As some comment already said a CTE can solve this

    with cte as (
    select item, wh, stock_in, stock_out, price, value
         , row_number() over (partition by item, wh order by item, wh) as rank
    from   myTable)
    select a.item, a.wh
         , a.stock_in - coalesce(b.stock_out, 0) stock
         , a.price
         , a.value - coalesce(b.value, 0) value
    from cte a
         left join cte b on a.item = b.item and a.wh = b.wh and a.rank = b.rank - 1
    where a.stock_in - coalesce(b.stock_out, 0) > 0
    

    If the second "Item B" has the wrong price (the IN price is 25, the OUT is 35).
    SQL 2008 fiddle

    Just for fun, with sql server 2012 and the introduction of the LEAD and LAG function the same thing is possible in a somewhat easier way

    with cte as (
    select item, wh, stock_in
         , coalesce(LEAD(stock_out) 
                    OVER (partition by item, wh order by item, wh), 0) stock_out
         , price, value
         , coalesce(LEAD(value) 
                    OVER (partition by  item, wh order by item, wh), 0) value_out
    from   myTable)
    select item
         , wh
         , (stock_in - stock_out) stock
         , price
         , (value - value_out) value
    from   cte
    where  (stock_in - stock_out) > 0
    

    SQL2012 fiddle

    Update
    ATTENTION -> To use the two query before this point the data need to be in the correct order.

    To have the details with more then one row per day you need something reliable to order the row with the same date, like a date column with time, an autoincremental ID or something down the same line, and it's not possible to use the query already written because they are based on the position of the data.

    A better idea is to split the data in IN and OUT, order it by item, wh and data, and apply a rank on both data, like this:

    SELECT d_in.item
         , d_in.wh
         , d_in.stock_in - coalesce(d_out.stock_out, 0) stock
         , d_in.price
         , d_in.value - coalesce(d_out.value, 0) value
    FROM   (SELECT item, wh, stock_in, price, value
                 , rank = row_number() OVER 
                   (PARTITION BY item, wh ORDER BY item, wh, date)
            FROM   myTable
            WHERE  stock_out = 0) d_in
           LEFT JOIN
           (SELECT item, wh, stock_out, price, value
                 , rank = row_number() OVER 
                   (PARTITION BY item, wh ORDER BY item, wh, date)
            FROM   myTable
            WHERE  stock_in = 0) d_out
           ON d_in.item = d_out.item AND d_in.wh = d_out.wh 
          AND d_in.rank = d_out.rank
    WHERE d_in.stock_in - coalesce(d_out.stock_out, 0) > 0
    

    SQLFiddle

    But this query is NOT completely reliable, the order of data in the same order group is not stable.

    I haven't change the query to recalculate the price if the IN.price is different from the OUT.price

    0 讨论(0)
  • 2020-12-14 04:51

    If cursors aren't an option, a SQLCLR stored procedure might be. This way you could obtain the raw data into .net objects, manipulate / sort it using c# or vb.net and set the resulting data as the procedure's output. Not only this will give you what you want, it may even turn up being much easier than trying to do the same in pure T-SQL, depending on your programming background.

    0 讨论(0)
提交回复
热议问题