SQL-计算产品的累计平均成本价

时间:2018-07-30 12:05:47

标签: sql sql-server database data-structures views

我想知道是否有人至少可以在这个问题上为我指明正确的方向。

我需要计算平均库存成本,但需要注意的是,仅应根据与我们所拥有的库存有关的最新产品采购来计算。

为更好地解释产品x,我们以不同的价格从各种供应商处购买了1200个单位。我们只剩下150个单位,因此,要获取平均购买价格和剩余商品的价值,我们需要从购买的最新150个单位中获取产品的平均成本。< / p>

我有一个产生以下内容的视图:

 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小提琴:

http://sqlfiddle.com/#!18/69288/1

您会看到我有三个采购订单:

1:数量为20,@£40ea
2:数量20 @£30ea
3:数量10 @£25ea

我有两个相同商品的订单:

1:数量10
2:数量15

由此,我可以库存: 25

我需要剩余的股票的平均购买价格。

我还有25个单位,所以我需要从最新的采购订单中倒退以获取价值。

我将从采购订单3中提取10,从采购订单2中提取15:

10 *£25 =£250
15 * 30英镑= 450英镑

700英镑/ 25 = 28英镑

我希望这可以使我的问题更清楚!

谢谢

更新2

非常感谢Sticky Bit,感谢您抽出宝贵时间为我的问题提供解决方案,并进行了周到的解释。

我已经在我的开发数据库上尝试过这个,似乎有问题。

我有4个相同产品的采购订单(其中2个在同一天下订单)

我还没有找到如何在此文本编辑器中优雅地设置表格格式的方法,请耐心等待:

PurchaseOrderId / PurchaseOrderDate
2 / 2018-07-28
3 / 2018-07-29
4 / 2018-07-30
5 / 2018-07-30

我有以下PurchaseOrderLine

PurchaseOrderLineId / PurchaseOrderId / 产品ID / 数量 / 单价
3/2/8 / 200.00 / 400.00
4/3/8/40 / 420.00
5/4/8/25 / 500.00
6/5/8/8 / 10.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日购买的产品的平均价格有所下降(它是采用两个价格之间的平均值,而不考虑数量-我不确定这是否是设计使然?)< / p>

如果我再运行以下命令:

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

再次,关于单价,这里似乎不对。

任何帮助都将不胜感激!

亲切的问候

2 个答案:

答案 0 :(得分:0)

我看不到“ UnitCost”,因此在代码示例中将使用“ UnitPrice”作为费用。

我不知道这是完美的,但是它可能会在正确的方向上为您提供帮助。

$form->handleRequest($request);
if ($form->isSubmitted() ) {
}

答案 1 :(得分:0)

  1. 首先,我们需要找到一个查询,以向我们提供每种产品的当前库存水平。为此,我们将连接purchaseorderlineorderline留给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;
    
  2. 接下来,我们需要为每种产品和每天(purchaseorders)存储的数量。为此,我们内部联接purchaseorderpurchaseorderline。我们再次汇总以考虑可能的情况,即同一天在同一产品上下了多个订单。

    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;