正解するのは意外と難しい。ウィンドウ関数での合計の実行をサポートする 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
に対して特別なことをする必要がないことです。 トランザクション - 合計数量を知る必要があるだけです。それが TotalOut
です CTE を計算します。最初の 2 つの CTE は IN
で動作します 取引を行い、それぞれが表す在庫の「間隔」を計算します - 最終クエリを select * from RunningTotals
に変更します
最後の SELECT
ステートメントは、発信トランザクションによって完全に使い尽くされていない行を見つけ、それがその着信トランザクションの全数量であるか、それとも発信合計にまたがるトランザクションであるかを判断します。