SQL - 计算产品的累积平均成本价
Posted
技术标签:
【中文标题】SQL - 计算产品的累积平均成本价【英文标题】:SQL - Calculate cumulative average cost price for a product 【发布时间】:2018-07-30 12:05:47 【问题描述】:我想知道是否有人至少可以为我指出这个问题的正确方向。
我需要计算平均库存成本,但需要注意的是,它应该只根据我们库存的最新产品采购来计算。
为了更好地解释产品 x,我们以不同的成本从不同的供应商处购买了 1,200 件产品。我们只剩下 150 件库存,因此,要获得剩余商品的平均购买价格和价值,我们需要从最近购买的 150 件仅中获取产品的平均成本。
我有一个产生以下结果的视图:
ProductId (int) - PK
ProductName (varchar(150))
StockInHand (int)
相关表格如下(为方便使用截断)
采购订单
PurchaseOrderId (int) - PK
PurchaseOrderDate (DateTime)
PurchaseOrderStatus (int) - FK
采购订单状态 - 1 = 打开,2 = 已签入
PurchaseOrderLine
PurchaseOrderLineId (int) - PK
Qty (int)
UnitPrice (decimal(18,2))
ProductId (int) - FK
PurchaseOrderId (int) - FK
更新
我在这里创建了一个 sql-fiddle:
http://sqlfiddle.com/#!18/69288/1
你会看到我有三个商品采购订单:
1:数量 20 @ 40 英镑 2:数量 20 @ £30ea 3:数量 10 @ 25 英镑
我有两个相同商品的订单:
1:数量 10 2:数量 15
由此,我可以得到手头的库存:25
我需要剩余股票的平均购买价格。
我还剩 25 件,所以我需要从最新的采购订单开始逆向计算才能获得价值。
我将从采购订单 3 中取出 10 个,从采购订单 2 中取出 15 个:
10 * 25 英镑 = 250 英镑 15 * 30 英镑 = 450 英镑
700 英镑 / 25 = 28 英镑
我希望这能让我的问题更清楚!
谢谢
更新 2
非常感谢 Sticky Bit 抽出时间发布我的问题的解决方案并如此周到地解释它。
我已在我的开发数据库上尝试过此操作,但似乎遇到了问题。
我有 4 个同一产品的采购订单(其中两个是在同一天下的)
我还没有弄清楚如何在这个文本编辑器中优雅地格式化表格,所以请多多包涵:
PurchaseOrderId / PurchaseOrderDate 2 / 2018-07-28 3 / 2018-07-29 4 / 2018-07-30 5 / 2018-07-30
我有以下 PurchaseOrderLine
PurchaseOrderLineId / PurchaseOrderId / ProductId / 数量 / UnitPrice 3 / 2 / 8 / 20 / 400.00 4 / 3 / 8 / 40 / 420.00 5 / 4 / 8 / 25 / 500.00 6 / 5 / 8 / 1 / 200.00
运行以下:
SELECT pol.productid,
po.purchaseorderdate,
sum(pol.qty) qty,
avg(pol.unitprice) unitprice
FROM purchaseorder po
INNER JOIN purchaseorderline pol
ON pol.purchaseorderid = po.purchaseorderid
GROUP BY pol.productid,
po.purchaseorderdate;
给我这些结果:
8 2018-07-28 00:00:00.000 20 400.000000 8 2018-07-29 00:00:00.000 40 420.000000 8 2018-07-30 00:00:00.000 26 350.000000
您会注意到,7 月 30 日购买的产品的平均成本有所下降(它采用两个价格之间的平均值,而不考虑数量 - 我不确定这是否是设计使然?)
如果我然后运行以下命令:
SELECT po.productid,
po.purchaseorderdate,
sum(po.qty) OVER (PARTITION BY po.productid
ORDER BY po.purchaseorderdate) qty,
sum(po.unitprice) OVER (PARTITION BY po.productid
ORDER BY po.purchaseorderdate) unitprice
FROM (SELECT pol.productid,
po.purchaseorderdate,
sum(pol.qty) qty,
avg(pol.unitprice) unitprice
FROM purchaseorder po
INNER JOIN purchaseorderline pol
ON pol.purchaseorderid = po.purchaseorderid
GROUP BY pol.productid,
po.purchaseorderdate) po;
我得到以下结果:
8 2018-07-28 00:00:00.000 20 400.000000 8 2018-07-29 00:00:00.000 60 820.000000 8 2018-07-30 00:00:00.000 86 1170.000000
同样,这里的单价似乎有些不对劲。
非常感谢任何帮助!
亲切的问候
【问题讨论】:
示例数据(可能还有sql-fiddle 上的示例模式将有助于为这个问题创建答案,因为目前很难看出问题是什么是实时数量和价格的唯一链接在同一张桌子上 嗨 WTP,我创建了一个 sql-fiddle 并相应地更新了我的原始帖子。 那么unitprice
是什么?我想这是每件的价格,所以一条线的总价格是unitprice * qty
。这个假设是否错误,unitprice
是整批的价格,即单个商品的价格是unitprice / qty
?最后你想得到什么,每件的平均价格还是这个价格乘以库存商品的数量?
嗨 Sticky Bit,不,你是对的。单价是每件商品的价格。我需要一件物品的平均成本价,与我们剩余的库存量有关。例如,使用我上面更新的信息,如果我们有 30 件库存商品,平均成本价格将为 466 英镑:(1 x 200 = 200 英镑)+(25 x 500 = 12,500 英镑)+(4 x 420 = £1,280) / 30 如果这有点令人困惑,我深表歉意。再次感谢您
【参考方案1】:
首先,我们需要找到一个查询来为我们提供每种产品的当前库存水平。为此,我们将 purchaseorderline
和 orderline
连接到 product
并计算每一行的差异。由于一个产品可以在多个订单中,我们另外汇总结果,以获得每个产品的总体差异 - 当前库存水平。
SELECT p.productid,
p.productname,
sum(coalesce(pol.qty, 0) - coalesce(ol.qty, 0)) qty
FROM product p
LEFT JOIN purchaseorderline pol
ON pol.productid = p.productid
LEFT JOIN orderline ol
ON ol.productid = p.productid
GROUP BY p.productid,
p.productname;
接下来,我们需要每个产品和日期的库存数量(purchaseorders
)。为此,我们内部连接purchaseorder
和purchaseorderline
。我们再次汇总以考虑可能的情况,即在同一天为同一产品订购了多个订单。
SELECT pol.productid,
po.purchaseorderdate,
sum(pol.qty) qty,
sum(pol.qty * pol.unitprice) unitprice
FROM purchaseorder po
INNER JOIN purchaseorderline pol
ON pol.purchaseorderid = po.purchaseorderid
GROUP BY pol.productid,
po.purchaseorderdate;
我们现在可以使用之前的结果和窗口函数来获得每天的库存数量和产品平均价格的总和。
SELECT po.productid,
po.purchaseorderdate,
sum(po.qty) OVER (PARTITION BY po.productid
ORDER BY po.purchaseorderdate) qty,
sum(po.unitprice) OVER (PARTITION BY po.productid
ORDER BY po.purchaseorderdate)
/
sum(po.qty) OVER (PARTITION BY po.productid
ORDER BY po.purchaseorderdate) unitprice
FROM (SELECT pol.productid,
po.purchaseorderdate,
sum(pol.qty) qty,
sum(pol.qty * pol.unitprice) unitprice
FROM purchaseorder po
INNER JOIN purchaseorderline pol
ON pol.purchaseorderid = po.purchaseorderid
GROUP BY pol.productid,
po.purchaseorderdate) po;
现在我们使用OUTER APPLY
将 1. 和 2. 的结果放在一起。对于每种产品,我们从 2 中选择TOP 1
结果。按天降序排列(即年轻订单优先),库存数量大于或等于当前库存数量。
SELECT p.productid,
p.productname,
po.unitprice
FROM (SELECT p.productid,
p.productname,
sum(coalesce(pol.qty, 0) - coalesce(ol.qty, 0)) qty
FROM product p
LEFT JOIN purchaseorderline pol
ON pol.productid = p.productid
LEFT JOIN orderline ol
ON ol.productid = p.productid
GROUP BY p.productid,
p.productname) p
OUTER APPLY (SELECT TOP 1
po.unitprice
FROM (SELECT po.productid,
po.purchaseorderdate,
sum(po.qty) OVER (PARTITION BY po.productid
ORDER BY po.purchaseorderdate) qty,
sum(po.unitprice) OVER (PARTITION BY po.productid
ORDER BY po.purchaseorderdate)
/
sum(po.qty) OVER (PARTITION BY po.productid
ORDER BY po.purchaseorderdate) unitprice
FROM (SELECT pol.productid,
po.purchaseorderdate,
sum(pol.qty) qty,
sum(pol.qty * pol.unitprice) unitprice
FROM purchaseorder po
INNER JOIN purchaseorderline pol
ON pol.purchaseorderid = po.purchaseorderid
GROUP BY pol.productid,
po.purchaseorderdate) po) po
WHERE po.productid = p.productid
AND po.qty >= p.qty
ORDER BY po.purchaseorderdate DESC) po;
【讨论】:
亲爱的 Sticky Bit,非常感谢您抽出时间帮助我解决这个问题。非常感谢。我已经更新了我的帖子,以显示我在您的解决方案中遇到的问题。再次感谢您 @GrantS:我编辑了我的答案。我希望我这次做对了?如果没有,我建议您添加一个更全面的数据集(到您的小提琴中)和(部分)结果,这适合它。 亲爱的 Sticky Bit,这看起来在计算平均价格方面非常有效。非常感谢你做的这些。唯一的问题是最终结果显示了我所有具有相同“单价”的产品的列表。我只有一种产品的购买记录,所以这些值应该是“空”吗?再次感谢您 亲爱的 Sticky Bit,我添加了以下内容: WHERE po.qty >= p.qty AND po.ProductId = p.ProductId 这似乎使它完美运行!然而,还有一件事。我有一个带有 ProductId、VariationName 的 ProductVariation 表。产品可以有零个或多个变体,我需要使用您提供的解决方案来解决这个问题。我应该将此标记为解决方案并创建一个更有条理的问题吗?我以为我可以自己推断解决方案,但我遇到了麻烦。亲切的问候, @GrantS:你说得对,我忘了链接productid
。我纠正了这一点。【参考方案2】:
我没有看到“UnitCost”,因此我将在代码示例中使用“UnitPrice”作为成本。
我不知道这是否完美,但它可能会帮助您朝着正确的方向前进。
SELECT (SUM(UnitPrice)/150) FROM OrderDetails
WHERE PurchaseOrderId IS BETWEEN 1050 AND 1200
GO
【讨论】:
您好 Jonah,非常感谢您抽出宝贵时间回复。您的解决方案并不是我真正想要的。我已经更新了我的原始帖子以更好地解释我的问题。再次感谢。以上是关于SQL - 计算产品的累积平均成本价的主要内容,如果未能解决你的问题,请参考以下文章