sql >> Databáze >  >> RDS >> Sqlserver

Oceňování zásob na základě FIFO v SQL Server

Překvapivě těžké se dostat správně. Mám podezření, že by bylo jednodušší použít SQL Server 2012, který podporuje průběžné součty ve funkcích oken. Každopádně:

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

První pozorování je, že pro OUT nemusíme dělat nic zvláštního transakce – stačí nám znát celkové množství. To je to, co TotalOut CTE počítá. První dva CTE pracují s IN transakce a vypočítejte, jaký „interval“ akcií každá představuje – změňte poslední dotaz na pouze select * from RunningTotals abyste měli pocit.

Poslední SELECT příkaz najde řádky, které nebyly zcela vyčerpány odchozími transakcemi, a poté rozhodne, zda se jedná o celé množství této příchozí transakce, nebo zda se jedná o transakci, která přesahuje celkový počet odchozích transakcí.



  1. Dochází ke snížení výkonu, pokud je v tabulce příliš mnoho sloupců?

  2. SQL není skupinová funkce s jednou skupinou

  3. Naučte se, jak provést proceduru v Toad For Oracle

  4. Many To Many Table Join with Pivot