3

我有一个这样的股票交易表:

Item   Date         TxnType Qty  Price
ABC   01-April-2012   IN    200 750.00
ABC   05-April-2012   OUT   100     
ABC   10-April-2012   IN     50 700.00
ABC   16-April-2012   IN     75 800.00
ABC   25-April-2012   OUT   175     
XYZ   02-April-2012   IN    150 350.00
XYZ   08-April-2012   OUT   120     
XYZ   12-April-2012   OUT    10     
XYZ   24-April-2012   IN     90 340.00

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

Item  Qty      Value
ABC   50    40000.00
XYZ   110   37600.00

请帮助我获得解决方案。

4

2 回答 2

5

出乎意料地难以正确。我怀疑使用支持在窗口函数中运行总和的 SQL Server 2012 会更容易。无论如何:

declare @Stock table (Item char(3) not null,[Date] datetime not null,TxnType varchar(3) not null,Qty int not null,Price decimal(10,2) null)
insert into @Stock(Item ,  [Date] ,        TxnType, Qty,  Price) values
('ABC','20120401','IN',    200, 750.00),
('ABC','20120405','OUT',   100 ,null  ),
('ABC','20120410','IN',     50, 700.00),
('ABC','20120416','IN',     75, 800.00),
('ABC','20120425','OUT',   175, null  ),
('XYZ','20120402','IN',    150, 350.00),
('XYZ','20120408','OUT',   120 ,null  ),
('XYZ','20120412','OUT',    10 ,null  ),
('XYZ','20120424','IN',     90, 340.00);

;WITH OrderedIn as (
    select *,ROW_NUMBER() OVER (PARTITION BY Item ORDER BY [DATE]) as rn
    from @Stock
    where TxnType = 'IN'
), RunningTotals as (
    select Item,Qty,Price,Qty as Total,0 as PrevTotal,rn from OrderedIn where rn = 1
    union all
    select rt.Item,oi.Qty,oi.Price,rt.Total + oi.Qty,rt.Total,oi.rn
    from
        RunningTotals rt
            inner join
        OrderedIn oi
            on
                rt.Item = oi.Item and
                rt.rn = oi.rn - 1
), TotalOut as (
    select Item,SUM(Qty) as Qty from @Stock where TxnType='OUT' group by Item
)
select
    rt.Item,SUM(CASE WHEN PrevTotal > out.Qty THEN rt.Qty ELSE rt.Total - out.Qty END * Price)
from
    RunningTotals rt
        inner join
    TotalOut out
        on
            rt.Item = out.Item
where
    rt.Total > out.Qty
group by rt.Item

第一个观察是我们不需要为OUT交易做任何特别的事情——我们只需要知道总量。这就是TotalOutCTE 计算的结果。前两个 CTE 处理IN交易,并计算每个股票的“间隔”代表什么 - 将最终查询更改为只是select * from RunningTotals为了感受一下。

最后的SELECT语句查找尚未被传出事务完全耗尽的行,然后确定它是该传入事务的全部数量,还是跨越传出总数的事务。

于 2012-04-26T07:02:33.543 回答
0

我认为您必须为此使用详细事务表。像Stock,StockDetail,StockDetailTransaction。在此 StockDetailTransaction 表中包含 Stock 的 FIFO 条目。当 Item In/Out 时在 StockDetailTransaction 中添加记录。

于 2012-04-26T05:37:36.003 回答