在T-SQL

时间:2017-07-20 21:55:35

标签: sql sql-server tsql

我有一张产品表,其中包含特定日期的销售,购买,开始和结束库存。为简单起见,我在下面的示例中省略了日期和其他产品。我试图使用T-SQL获得产品的平均成本。我对这个问题感到困惑,因为它依赖于之前的记录(天)的AvgCost,它从一开始就是空的。

示例数据

DECLARE @tbl TABLE (Id INT IDENTITY, ProductId INT, 
    BeginInvt DECIMAL(9,2), SaleQty DECIMAL(9,2), SalePrice DECIMAL(5,3), 
    PurQty DECIMAL(9,2) NULL, PurCost DECIMAL(5,3) NULL, EndingInvt DECIMAL(9,2))

INSERT @tbl (ProductId, BeginInvt, SaleQty, SalePrice, PurQty, PurCost, EndingInvt )
VALUES 
(1,3000,500,2.000,NULL,NULL,2500),
(1,2500,250,2.000,2000,1.800,4250),
(1,4250,300,2.000,NULL,NULL,3950),
(1,3950,900,2.000,4000,1.850,7050),
(1,7050,300,2.000,NULL,NULL,6750),
(1,6750,300,2.000,NULL,NULL,6450),
(1,6450,300,2.000,5000,1.750,11150),
(1,11150,300,2.000,NULL,NULL,10850)

我想获得上述行的AvgCost。鉴于3000件物品的平均成本的初始库存为1.9。解决方案应该有这样的结果

我正在寻找具有AvgCost列的输出,如下所示。该表可以有不同的产品。一旦我有解决方案,我可以应用窗口函数来分区计算。

预期结果

Id   ProductId   BeginInvt   SaleQty  SalePrice  PurQty    PurCost  EndingInvt  AvgCost
---- ----------- ----------- -------- ---------- --------- -------- ----------- --------
1    1           3000.00     500.00   2.000      NULL      NULL     2500.00     1.90000
2    1           2500.00     250.00   2.000      2000.00   1.800    4250.00     1.85556
3    1           4250.00     300.00   2.000      NULL      NULL     3950.00     1.85556
4    1           3950.00     900.00   2.000      4000.00   1.850    7050.00     1.85276
5    1           7050.00     300.00   2.000      NULL      NULL     6750.00     1.85276
6    1           6750.00     300.00   2.000      NULL      NULL     6450.00     1.85276
7    1           6450.00     300.00   2.000      5000.00   1.750    11150.00    1.80789
8    1           11150.00    300.00   2.000      NULL      NULL     10850.00    1.80789

可以通过对BeginInvt和Pur值进行加权平均来计算行的AvgCost,如下所示:

((BeginInvt*prevous_day_avgcost)+(PurQty*PurCost))/(BeginInvt+PurQty)

prevous_day_avgcost 对我来说是基于设置的计算的问题

感谢您的帮助...

1 个答案:

答案 0 :(得分:1)

使用递归cte的一种方法。这是因为在上一次计算完成之前,您不会知道每行的avgCost。所以你可以迭代地做到这一点。

with rownums as (select t.*,row_number() over(partition by productId order by id) as rnum from @tbl t)
,cte as (select rnum,id,ProductId, BeginInvt, SaleQty, SalePrice, 
         PurQty, PurCost, EndingInvt ,cast(1.9 as decimal(38,5)) as avgCost --replace this with a calculation if you know it.
         from rownums 
         where rnum=1
         union all
         select r2.rnum,r2.id,r2.ProductId, r2.BeginInvt, r2.SaleQty, r2.SalePrice, r2.PurQty, r2.PurCost, r2.EndingInvt, 
         cast(((r2.BeginInvt*r1.avgCost)+(coalesce(r2.PurQty,0)*coalesce(r2.PurCost,0)))/(r2.BeginInvt+coalesce(r2.PurQty,0)) as decimal(38,5))
         from cte r1
         join rownums r2 on r1.productId=r2.productId and r2.rnum=r1.rnum+1
        ) 
select ProductId, BeginInvt, SaleQty, SalePrice, PurQty, PurCost, EndingInvt, avgCost
from cte

Sample Demo