Sql server 2012 计算管道和桩长度的运行成本
我在一家小公司工作,我们正试图摆脱Excel工作簿的库存控制。我以为我已经在纳赛尔的帮助下解决了这个问题,但我无能为力。这是我能进入一张桌子的东西,从那里我也需要得到它,使它看起来像下面的桌子 我的数据 预期产量 组的第一个记录将被视为期初余额。进料场的存货ID为1,出料场的存货ID为2。进入堆场的装载进尺总是有每英尺的装载成本,我可以计算出进尺的运行总成本。组的第一个记录很容易计算运行成本和每英尺运行成本。下一条记录变得更难计算。我需要将每英尺的平均运行成本向前移动到当有东西离开院子时每英尺的负载成本,然后再次计算运行成本和每英尺的平均运行成本。希望这对某些人来说是有意义的,我们可以自动完成一些计算。谢谢你的帮助 下面是我发现的一个Oracle示例Sql server 2012 计算管道和桩长度的运行成本,sql-server-2012,Sql Server 2012,我在一家小公司工作,我们正试图摆脱Excel工作簿的库存控制。我以为我已经在纳赛尔的帮助下解决了这个问题,但我无能为力。这是我能进入一张桌子的东西,从那里我也需要得到它,使它看起来像下面的桌子 我的数据 预期产量 组的第一个记录将被视为期初余额。进料场的存货ID为1,出料场的存货ID为2。进入堆场的装载进尺总是有每英尺的装载成本,我可以计算出进尺的运行总成本。组的第一个记录很容易计算运行成本和每英尺运行成本。下一条记录变得更难计算。我需要将每英尺的平均运行成本向前移动到当有东西离开院子时每英尺的
SQL> select order_id
2 , volume
3 , price
4 , total_vol
5 , total_costs
6 , unit_costs
7 from ( select order_id
8 , volume
9 , price
10 , volume total_vol
11 , 0.0 total_costs
12 , 0.0 unit_costs
13 , row_number() over (order by order_id) rn
14 from costs
15 order by order_id
16 )
17 model
18 dimension by (order_id)
19 measures (volume, price, total_vol, total_costs, unit_costs)
20 rules iterate (4)
21 ( total_vol[any] = volume[cv()] + nvl(total_vol[cv()-1],0.0)
22 , total_costs[any]
23 = case SIGN(volume[cv()])
24 when -1 then total_vol[cv()] * nvl(unit_costs[cv()-1],0.0)
25 else volume[cv()] * price[cv()] + nvl(total_costs[cv()-1],0.0)
26 end
27 , unit_costs[any] = total_costs[cv()] / total_vol[cv()]
28 )
29 order by order_id
30 /
ORDER_ID VOLUME PRICE TOTAL_VOL TOTAL_COSTS UNIT_COSTS
---------- ---------- ---------- ---------- ----------- ----------
1 1000 100 1000 100000 100
2 -500 110 500 50000 100
3 1500 80 2000 170000 85
4 -100 150 1900 161500 85
5 -600 110 1300 110500 85
6 700 105 2000 184000 92
选择6行。让我先说三件事: 这当然不是最好的办法。有一条规则说,如果你需要一个while循环,那么你很可能是做错了什么。 我怀疑您的原始预期输出中存在一些计算错误,请检查计算,因为根据您的公式,我的计算值不同。 这个问题也可以被视为一种问题,但由于您提出了一个形式合理的问题,并进行了一些后续研究,我的答案如下。因此,无需向上投票,因为这对特定案例有帮助 现在谈谈解决方案: 我试图在一个格式良好的update语句中使用该语句的初始提示,但由于您只能在select或order by子句中使用一个窗口函数,即LAG,所以这将不起作用 简而言之,以下代码的作用是: 当可以计算每个记录时,它会计算每个记录的各种计算字段,并使用适当的函数更新表,然后移动到下一个记录。 有关更多信息,请参见代码中的注释。 Detritable是链接的SQLFiddle中可见的演示表。 有关小数点19,4的信息,请阅读此内容 输出包括示例数据和演示其工作原理的示例: ID GrpID InOut LoadFt RunFt LoadCost RunCost LoadCostFt AvgRunCostFt 1 1 1 4549 4549 4503.51 4503.51 0.99 0.99 2 1 1 1523.22 6072.22 1964.9538 6468.4638 1.29 1.0653 3 1 2 -2491.73 3580.49 -2654.44 3814.0238 1.0653 1.0652 4 1 2 -96 3484.49 -102.2592 3711.7646 1.0652 1.0652 5 1 1 8471.68 11956.17 11945.0688 15656.8334 1.41 1.3095 6 1 2 -369 11587.17 -483.2055 15173.6279 1.3095 1.3095 7 2 1 1030.89 1030.89 5226.6123 5226.6123 5.07 5.07 8 2 1 314.17 1345.06 1806.4775 7033.0898 5.75 5.2288 9 2 1 239.56 1584.62 1509.228 8542.3178 6.3 5.3908 10 2 2 -554.46 1030.16 -2988.983 5553.3348 5.3908 5.3907 11 2 1 826.24 1856.4 4861.5962 10414.931 5.884 5.6103
如果您不清楚代码的某些部分,我可以用其他解释来更新。我将在这里提示您这么久。如果其他人当时没有,您将在稍后写下答案。在您的数据中,所有输出记录的LoadCostft为0,但在预期数据中,所有记录都有一个值。是否有用于计算它们的特定计算?应该是上一行的RunCost/RunFt=AvgRunCostFt,其中InOut=2和GrpID=GrpID。我希望这有帮助,如果你需要更多的信息,请让我知道。谢谢你看这个。用会计术语来说,我想他们称之为移动平均库存法,相当于先进先出或后进先出。哇,我在经历这件事和观看卡尔加里-阿纳海姆季后赛曲棍球比赛之间左右为难。你能在SO之外得到联系和感谢吗?你可以通过贡献SO来感谢我:我投入了很多,在第二节课之后,我们什么都没输,你回答得再好不过了。结果不言而喻,我对你感激不尽。我会尽力帮忙,所以无论我在哪里,它都是一个值得支持的网站。你对我错误的自由手预期输出表很了解,而且很友好,而且仍然在努力地完成它。我认为你的回答是非常好的。
SQL> select order_id
2 , volume
3 , price
4 , total_vol
5 , total_costs
6 , unit_costs
7 from ( select order_id
8 , volume
9 , price
10 , volume total_vol
11 , 0.0 total_costs
12 , 0.0 unit_costs
13 , row_number() over (order by order_id) rn
14 from costs
15 order by order_id
16 )
17 model
18 dimension by (order_id)
19 measures (volume, price, total_vol, total_costs, unit_costs)
20 rules iterate (4)
21 ( total_vol[any] = volume[cv()] + nvl(total_vol[cv()-1],0.0)
22 , total_costs[any]
23 = case SIGN(volume[cv()])
24 when -1 then total_vol[cv()] * nvl(unit_costs[cv()-1],0.0)
25 else volume[cv()] * price[cv()] + nvl(total_costs[cv()-1],0.0)
26 end
27 , unit_costs[any] = total_costs[cv()] / total_vol[cv()]
28 )
29 order by order_id
30 /
ORDER_ID VOLUME PRICE TOTAL_VOL TOTAL_COSTS UNIT_COSTS
---------- ---------- ---------- ---------- ----------- ----------
1 1000 100 1000 100000 100
2 -500 110 500 50000 100
3 1500 80 2000 170000 85
4 -100 150 1900 161500 85
5 -600 110 1300 110500 85
6 700 105 2000 184000 92
-- Our state and running variables
DECLARE @curId INT = 0,
@curGrpId INT,
@prevId INT = 0,
@prevGrpId INT = 0,
@LoadCostFt DECIMAL(19, 4),
@RunFt DECIMAL(19, 4),
@RunCost DECIMAL(19, 4)
WHILE EXISTS (SELECT 1
FROM TempTable
WHERE DoneFlag = 0) -- DoneFlag is a bit column I added to the table for calculation purposes, could also be called "IsCalced"
BEGIN
SELECT top 1 -- top 1 here to get the next row based on the ID column
@prevId = @curId,
@curId = tmp.ID,
@curGrpId = Grpid
FROM TempTable tmp
WHERE tmp.DoneFlag = 0
ORDER BY tmp.GrpID, tmp.ID -- order by to ensure that we get everything from one GrpID first
-- Calculate the LoadCostFt.
-- It is either predetermined (if InOut = 1) or derived from the previous record's AvgRunCostFt (if InOut = 2)
SELECT @LoadCostFt = CASE
WHEN tmp.INOUT = 2
THEN (lag(tmp.AvgRunCostFt, 1, 0.0) OVER (partition BY GrpId ORDER BY ID))
ELSE tmp.LoadCostFt
END
FROM TempTable tmp
WHERE tmp.ID IN (@curId, @prevId)
AND tmp.GrpID = @curGrpId
-- Calculate the LoadCost
UPDATE TempTable
SET LoadCost = LoadFt * @LoadCostFt
WHERE Id = @curId
-- Calculate the current RunFt and RunCost based on the current LoadFt and LoadCost plus the previous row's RunFt and RunCost
SELECT @RunFt = (LoadFt + (lag(RunFt, 1, 0) OVER (partition BY GrpId ORDER BY ID))),
@RunCost = (LoadCost + (lag(RunCost, 1, 0) OVER (partition BY GrpId ORDER BY ID)))
FROM TempTable tmp
WHERE tmp.ID IN (@curId, @prevId)
AND tmp.GrpID = @curGrpId
-- Set all our values, including the AvgRunCostFt calc
UPDATE TempTable
SET RunFt = @RunFt,
RunCost = @RunCost,
LoadCostFt = @LoadCostFt,
AvgRunCostFt = @RunCost / @RunFt,
doneflag = 1
WHERE ID = @curId
END
SELECT ID, GrpID, InOut, LoadFt, RunFt, LoadCost,
RunCost, LoadCostFt, AvgRunCostFt
FROM TempTable
ORDER BY GrpID, Id
ID GrpID InOut LoadFt RunFt LoadCost RunCost LoadCostFt AvgRunCostFt
1 1 1 4549 4549 4503.51 4503.51 0.99 0.99
2 1 1 1523.22 6072.22 1964.9538 6468.4638 1.29 1.0653
3 1 2 -2491.73 3580.49 -2654.44 3814.0238 1.0653 1.0652
4 1 2 -96 3484.49 -102.2592 3711.7646 1.0652 1.0652
5 1 1 8471.68 11956.17 11945.0688 15656.8334 1.41 1.3095
6 1 2 -369 11587.17 -483.2055 15173.6279 1.3095 1.3095
7 2 1 1030.89 1030.89 5226.6123 5226.6123 5.07 5.07
8 2 1 314.17 1345.06 1806.4775 7033.0898 5.75 5.2288
9 2 1 239.56 1584.62 1509.228 8542.3178 6.3 5.3908
10 2 2 -554.46 1030.16 -2988.983 5553.3348 5.3908 5.3907
11 2 1 826.24 1856.4 4861.5962 10414.931 5.884 5.6103