你如何进行查询来计算消耗了多少物品(用完了)?
我们可以在购买表中找到我们购买的每个商品的数量,其中包括列Id,ProductId,数量(十进制),日期
Id, ProductId, Qty, Date
1, 1, 10, 1/1/11
2, 1, 5, 2/2/11
3, 1, 8, 3/3/11
Run Code Online (Sandbox Code Playgroud)
那你如何计算购买表中每行消耗的数量 - 假设严格的FIFO?所以在上面的例子中,如果我们知道已经消耗了14个,那么输出将是:
Id, ProductId, Qty, Date, Consumed
1, 1, 10, 1/1/11, 10
2, 1, 5, 2/2/11, 4
3, 1, 8, 3/3/11, 0
Run Code Online (Sandbox Code Playgroud)
希望这能解释我所说的消费金额的意思 - 我们知道有14个被消费,而且第一次购买是10,所以所有10个消费.下一次购买是5,所以我们知道其中4个已被消费.
我可以从两个地方获取消耗的数据 - ConsumedItems表:列Id,ProductId,QtyUsed,Date),或者来自ConsumedSummaryView,其中包含ProductId,QtyUsed(这是ConsumedItems.QtyUsed的总和)
样本表和视图
create table purchases (Id int, ProductId int, Qty int, Date datetime)
insert purchases select 1, 1, 10, '1/1/11'
insert purchases select 2, 1, 5, '2/2/11'
insert purchases select 3, 1, 8, '3/3/11'
create view ConsumedSummaryView as select ProductID = 1, QtyUsed = 14
Run Code Online (Sandbox Code Playgroud)
查询
;with p as (
select *, rn=ROW_NUMBER() over (partition by productid order by date, id)
from purchases)
, tmp(Id, ProductId, Qty, Date, rn, ToGo, Consumed) as (
select p.Id, p.ProductId, p.Qty, p.Date, cast(1 as bigint),
CAST(ISNULL(v.qtyused,0) - p.Qty as decimal(20,10)),
cast(case
when v.qtyused >= p.Qty Then p.Qty
when v.qtyused > 0 then v.qtyused
else 0 end as decimal(20,10))
from p
left join ConsumedSummaryView v on p.ProductId = v.productId
where rn=1
union all
select p.Id, p.ProductId, p.Qty, p.Date, cast(p.rn as bigint),
cast(ISNULL(tmp.toGo,0) - p.Qty as decimal(20,10)),
cast(case
when tmp.toGo >= p.Qty Then p.Qty
when tmp.toGo > 0 then tmp.toGo
else 0 end as decimal(20,10))
from tmp
--inner join p on p.rn=tmp.rn+1
inner join p on p.rn=tmp.rn+1 and p.productid = tmp.ProductId
)
select Id, ProductId, Qty, Date, Consumed
from tmp
order by rn
Run Code Online (Sandbox Code Playgroud)
产量
Id ProductId Qty Date Consumed
----------- ----------- ----------- ----------------------- -----------
1 1 10 2011-01-01 00:00:00.000 10
2 1 5 2011-02-02 00:00:00.000 4
3 1 8 2011-03-03 00:00:00.000 0
Run Code Online (Sandbox Code Playgroud)