使用SQL在库存中实现FIFO

时间:2014-04-08 11:48:50

标签: sql sql-server fifo

这基本上是一个库存项目,分别通过购买和销售跟踪物品的“库存”和“库存”。

库存系统遵循FIFO方法(首先购买的物品总是先出售)。例如:

  

如果我们在1月,2月和3月购买了商品A.   当顾客到来时,我们会赠送1月份购买的商品   只有当1月份的项目结束时,我们才会开始赠送2月份的物品等等

所以我必须在这里显示我手中的总库存和拆分,以便我可以看到所产生的总成本。

实际表格数据:

Actual table data

我需要获得的结果集:

What the result set is meant to be

我的客户坚持认为我不应该使用Cursor,那么还有其他方法吗?

2 个答案:

答案 0 :(得分:12)

正如一些评论已经说过,CTE可以解决这个问题

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

如果第二个“项目B”的价格错误(IN价格为25,则OUT为35) SQL 2008 fiddle

只是为了好玩,使用sql server 2012并引入LEAD和LAG功能同样可以采用更简单的方式

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

<强>更新
注意 - &gt;要在此点之前使用两个查询,数据需要按正确的顺序排列。

要获得每天多于一行的详细信息,您需要一些可靠的东西来订购具有相同日期的行,例如带有时间的日期列,自动增量ID或同一行中的某些行,并且无法使用已写入的查询,因为它们基于数据的位置。

更好的想法是将数据拆分为IN和OUT,按项目,wh和数据排序,并对这两个数据应用排名,如下所示:

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

但是此查询 NOT 完全可靠,同一订单组中的数据顺序不稳定。

如果IN.price与OUT.price不同,我没有更改查询以重新计算价格

答案 1 :(得分:2)

如果游标不是一个选项,则可能是SQLCLR stored procedure。这样,您可以将原始数据获取到个对象,使用对其进行操作/排序,并将结果数据设置为过程的输出。不仅这会给你你想要的东西,它甚至比在纯T-SQL中尝试做同样容易,这取决于你的编程背景。