sql >> Database teknologi >  >> RDS >> Sqlserver

FIFO-baseret lagerbeholdningsvurdering i SQL Server

Overraskende svært at få ret. Jeg formoder, at det ville være nemmere at bruge SQL Server 2012, som understøtter kørende summer i vinduesfunktioner. Under alle omstændigheder:

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

Den første observation er, at vi ikke behøver at gøre noget særligt for OUT transaktioner - vi skal bare kende den samlede mængde. Det er hvad TotalOut CTE beregner. De første to CTE'er fungerer med IN transaktioner, og udregn, hvilket "interval" af lager hver repræsenterer - skift den endelige forespørgsel til bare at select * from RunningTotals for at få en fornemmelse af det.

Den endelige SELECT statement finder rækker, som ikke er blevet fuldstændig opbrugt af udgående transaktioner, og beslutter derefter, om det er hele mængden af ​​den indgående transaktion, eller om det er den transaktion, der dækker den udgående total.



  1. Sådan udføres genereret script (.sql-fil) med skema og data i SQL Server 2008

  2. Java/MSSQL:java.sql.SQLException Ugyldigt objektnavn 'TableName'

  3. Fysisk placering af FILESTREAM-data

  4. Indlæser CSV i MySQL-tabel med PHP