有关库存和价值的FIFO SQL查询

时间:2017-07-22 09:39:41

标签: c# sql sql-server

我有一个像这样的股票Ledger表:

    item  date           time      in_qty  out_qty  in_Price  out_Price
    ABC   01-April-2012  00:00:00  200              750.00   
    ABC   05-April-2012  00:00:00          100                800.00     
    ABC   10-April-2012  00:00:00  50               700.00                      
    ABC   16-April-2012  00:00:00  75               800.00
    ABC   25-April-2012  00:00:00          175                850.00
    XYZ   02-April-2012  00:00:00  150              350.00
    XYZ   08-April-2012  00:00:00          120               380.00
    XYZ   12-April-2012  00:00:00          80                370.00
    XYZ   24-April-2012  00:00:00  80               330.00
    XYZ   24-April-2012  00:00:00  90               340.00      
    LPQ   26-April-2012  00:00:00  70               240.00
    LPQ   27-April-2012  00:00:00  30               230.00  

我需要FIFO中每个项目的库存价值(先进先出),这意味着应首先消费第一个购买的商品。上述数据的输出库存估值为:

    Item    Qty   Value
    ABC     50    40000
    XYZ     110   40500
    LPQ     100   23700

请帮助我在FIFO中获得解决方案

1 个答案:

答案 0 :(得分:0)

我得到了我的预期,

declare @Stock table (item char(3) not null,[date] date not null,[time] time not null,in_qty decimal(18,5) null,out_qty decimal(18,5) null,in_Price decimal(10,2) null,out_Price decimal(10,2) null)
insert into @Stock(item , [date] ,[time] , in_qty, out_qty, in_Price,out_Price) values
('ABC','20120401','00:00:00',200 ,0 ,750 ,0),
('ABC','20120401','00:00:00',0 ,100 ,0 ,800),
('ABC','20120401','00:00:00',50 ,0 ,700 ,0),
('ABC','20120401','00:00:00',75 ,0 ,800 ,0),
('ABC','20120401','00:00:00',0 ,175 ,0 ,850),
('XYZ','20120401','00:00:00',150 ,0 ,350 ,0),
('XYZ','20120401','00:00:00',0 ,120 ,0 ,380),
('XYZ','20120401','00:00:00',0 ,80 ,0 ,370),
('XYZ','20120401','00:00:00',80 ,0 ,330 ,0),
('XYZ','20120401','00:00:00',90 ,0 ,340 ,0),
('PQR','20120401','00:00:00',70 ,0 ,240 ,0),
('PQR','20120401','00:00:00',30 ,0 ,230 ,0)

;WITH OrderedIn as 
    (
        select *,ROW_NUMBER()OVER (PARTITION BY item ORDER BY date asc,time asc) as S_No
        from @Stock
        where in_qty <> 0
    ),  RunningTotals as 
    (
        select item, in_qty, in_Price as price, cast(in_qty as varchar(100)) as Total
                ,cast(0 as varchar(100)) as PrevTotal,S_No from OrderedIn where S_No = 1
        union all
        select rt.item ,oi.in_qty ,oi.in_Price as price 
                ,cast(rt.Total + oi.in_qty as varchar(100)),cast(rt.Total as varchar(100)),oi.S_No
        from
                RunningTotals rt
            inner join OrderedIn oi 
                on rt.item = oi.item
                and rt.S_No = oi.S_No - 1
    ), TotalOut as 
    (
        select item,SUM(out_qty) as Qty from @Stock where out_Price <> 0 group by item
    )
    select  
         rt.item
        ,SUM(CASE WHEN PrevTotal > COALESCE(out.Qty,0) THEN rt.in_qty ELSE rt.Total - COALESCE(out.Qty,0) END) as Qty
        ,SUM(CASE WHEN PrevTotal > COALESCE(out.Qty,0) THEN rt.in_qty ELSE rt.Total - COALESCE(out.Qty,0) END * (price)) as Value
    from
        RunningTotals rt
            left join
        TotalOut out
            on
                rt.item = out.item
    where
        rt.Total > COALESCE(out.Qty,0)
    group by rt.item

第一个观察是我们不需要为OUT交易做任何特殊事情 - 我们只需要知道总量。这就是TotalOut CTE计算的内容。前两个CTE使用IN事务,并计算什么&#34; interval&#34;每个代表的库存 - 将最终查询更改为从RunningTotals中选择*以获得感觉。

如果您有日期和时间的单独列,那么您应该先按日期分组然后按时间分组。

  • 在FIFO(先进先出)评估中按日期和时间分组升序