【发布时间】:2013-07-22 11:06:51
【问题描述】:
我从搜索这个网站中得到的最接近的是: Inventory Average Cost Calculation in SQL
但不幸的是,它是特定于 oracle 的,使用模型子句。
让我们开始吧。
有两个表:
-持有库存交易的人,以及
-持有最新库存估价的那个
我正在尝试使用基于特定日期的平均成本计算方法制作库存估价报告。
以正常方式进行,从开始计算到特定日期,将产生可变的响应时间。
想象一下计算价值五年的数据(以及数千种不同的库存项目)。
这将需要相当长的时间(而且我的公司不是硅谷级的。意思是,只有 2 核 cpu 和 8 GB 的 RAM)
所以我是向后计算的:从最近的(当前)回溯到那个特定的日期。
(每个月会计部门都会检查数据,所以计算只会处理1个月的数据,永远。 等于一致不变的性能)
我已在下面的脚本中将表格合并为一个
create table test3 ( rn integer, amt numeric, qty integer, oqty integer);
insert into test3 (rn,amt,qty,oqty) values (0,2260038.16765793,8,0);
insert into test3 (rn,amt,qty,oqty) values (1,1647727.2727,3,0);
insert into test3 (rn,amt,qty,oqty) values (2,2489654.75326715,0,1);
insert into test3 (rn,amt,qty,oqty) values (3,2489654.75326715,0,1);
insert into test3 (rn,amt,qty,oqty) values (4,1875443.6364,1,0);
insert into test3 (rn,amt,qty,oqty) values (5,1647727.2727,3,0);
insert into test3 (rn,amt,qty,oqty) values (6,3012987.01302857,0,1);
insert into test3 (rn,amt,qty,oqty) values (7,3012987.01302857,0,1);
select * from test3; (already sorted desc so rn=1 is the newest transaction)
rn amt qty oqty
0 2260038.168 8 0 --> this is the current average
1 1647727.273 3 0
2 2489654.753 0 1
3 2489654.753 0 1
4 1875443.636 1 0
5 1647727.273 3 0
6 3012987.013 0 1
7 3012987.013 0 1
with recursive
runsum (id,amt,qty,oqty,sqty,avg) as
(select data.id, data.amt, data.qty, data.oqty, data.sqty, data.avg
from (
select rn as id,amt,qty, oqty,
sum(case when rn=0 then qty else
case when oqty=0 then qty*-1
else oqty end end) over (order by rn) as sqty, lag(amt) over (order by rn) as avg
from test3 ) data
),
trans (id,amt,qty,oqty,sqty,prevavg,avg) as
(select id,amt,qty,oqty, sqty,avg,avg
from runsum
union
select runsum.id,trans.amt,trans.qty, trans.oqty, trans.sqty, lag(trans.avg) over (order by 1),
case when runsum.sqty=0 then runsum.amt else
((trans.prevavg*(runsum.sqty+trans.qty))-(runsum.amt*trans.qty)+(trans.prevavg*trans.oqty))/(runsum.sqty+trans.oqty)
end
from runsum join trans using (id))
select *
from trans
where prevavg is null and avg is not null
order by id;
结果应该是这样的
rn amt qty oqty sum avg
1 1647727.273 3 0 5 2627424.705
2 2489654.753 0 1 6 2627424.705
3 2489654.753 0 1 7 2627424.705
4 1875443.636 1 0 6 2752754.883
5 1647727.273 3 0 3 3857782.493
6 3012987.013 0 1 4 3857782.493
7 3012987.013 0 1 5 3857782.493
但是我得到了这个
id amt qty oqty sqty avg
1 1647727.273 3 0 5 2627424.705
2 2489654.753 0 1 6 2627424.705
3 2489654.753 0 1 7 2627424.705
5 1647727.273 3 0 3 3607122.137 --> id=4 is missing thus
screwing the calculation
and id=6 in turn dissappears tpp
7 3012987.013 0 1 5 3607122.137
我大吃一惊。 哪里错了?
感谢您的热心帮助。
已编辑
Average Costing Method 回溯(给定当前 avg 计算最后一次交易 avg,依此类推,直到第 n 次交易)
Avg (n) = ((Avg(n-1) * (Cum Qty(n)+In Qty(n))) - (In Amount(n) * In Qty (n)) + (Avg(n-1) * Out Qty(n))/(Cum Qty(n)+Out Amount(n))
回溯交易的累积数量将减去输入,加上输出。 因此,如果当前数量为 8,则之前的交易数量为 3,则该交易的累计数量为 5。
要计算上一笔交易的平均值,我们使用当前平均值来计算该交易。
@kordirko 的帮助提供的当前答案
with recursive
runsum (id,amt,qty,oqty,sqty,avg) as
(select data.id, data.amt, data.qty, data.oqty, data.sqty, data.avg
from (
select rn as id,amt,qty, oqty,
sum(case when rn=0 then qty else
case when oqty=0 then qty*-1
else oqty end end) over (order by rn) as sqty, lag(amt) over (order by rn) as avg
from test3 ) data
),
counter (maximum) as
(select count(rn)
from test3
),
trans (n, id,amt,qty,oqty,sqty,prevavg,avg) as
(select 0 n, id,amt,qty,oqty, sqty,avg,avg
from runsum
union
select trans.n+1, runsum.id,trans.amt,trans.qty, trans.oqty, trans.sqty,
lag(trans.avg) over (order by 1),
case when runsum.sqty=0 then runsum.amt else
((trans.prevavg*(runsum.sqty+trans.qty))-(runsum.amt*trans.qty)+(trans.prevavg*trans.oqty))/(runsum.sqty+trans.oqty)
end
from runsum join trans using (id)
where trans.n<(select maximum*2 from counter))
select *
from trans
where prevavg is null and avg is not null
order by id;
【问题讨论】:
-
请用几句话解释您用来生成输出行的算法。从错误的查询中很难发现应该如何进行正确的计算。
-
已添加说明。感谢您的回复
-
尝试使用
union all而不仅仅是union以避免删除重复项 -
感谢@a_horse_with_no_name 的建议。我试过了。没有成功。
标签: sql postgresql recursion