用于将库存分配给即将发货的SQL查询

时间:2017-04-07 19:13:30

标签: sql sql-server

我正在尝试自动执行将库存分配给未来货件的手动功能,以确定何时需要再次生产零件。所以在一个简单的例子中:

稍微清理一下这个例子:

Table ShipmentSchedule

Part   ShipmentNumber    QtyNeeded    
 1          1               30
 1          2               30 
 1          3               30 
 2          1               40
 2          2               40
Table Inventory

Part    QtyInventory
 1          40
 2          50

我想获得一个输出以下内容的查询。它需要每个零件的库存量,并使用库存来完成装运,直到库存用完为止。

Part    Shipment   Qty Need    Inventory Used    Qty to Produce
  1        1          30           30              0
  1        2          30           10             20 
  1        3          30            0             30 
  2        1          40           40              0 
  2        2          40            0             40  

1 个答案:

答案 0 :(得分:3)

这是一种方法。另外,我认为根据样本数据集,预期输出中的最后一行是错误的...

declare @ShipmentSchedule table (Part int, ShipmentNumber int, QtyNeeded int)
insert into @ShipmentSchedule
values
(1,1,30),
(1,2,30),
(1,3,30),
(2,1,40),
(2,2,40)

declare @Inventory table (Part int, QtyInventory int)
insert into @Inventory
values
(1,40),
(2,50)


--if you want the Quantity To Produce to keep incrementing (as a running total), so you only need to take the last one, then use this
select
    s.Part
    ,s.ShipmentNumber
    ,s.QtyNeeded
    ,case 
        when i.QtyInventory - sum(s.QtyNeeded) over (partition by s.Part order by s.Part, s.ShipmentNumber) > 0 
            then QtyNeeded
        when QtyNeeded + (i.QtyInventory - sum(s.QtyNeeded) over (partition by s.Part order by s.Part, s.ShipmentNumber)) > 0 
            then QtyNeeded + (i.QtyInventory - sum(s.QtyNeeded) over (partition by s.Part order by s.Part, s.ShipmentNumber))
        else 0
    end as InventoryUsed
    ,case 
            when i.QtyInventory - sum(s.QtyNeeded) over (partition by s.Part order by s.Part, s.ShipmentNumber) > 0 
                then 0
            when i.QtyInventory - sum(s.QtyNeeded) over (partition by s.Part order by s.Part, s.ShipmentNumber) < 0 
                then (i.QtyInventory - (sum(s.QtyNeeded) over (partition by s.Part order by s.Part, s.ShipmentNumber))) * - 1 
    end as QtyToProduce
from
    @ShipmentSchedule s
    inner join
    @Inventory i on i.Part = s.Part


--or if you want how many to produce per shipment... wrap you can use a cte
;with cte as(
    select
        s.Part
        ,s.ShipmentNumber
        ,s.QtyNeeded
        ,case 
            when i.QtyInventory - sum(s.QtyNeeded) over (partition by s.Part order by s.Part, s.ShipmentNumber) > 0 
                then QtyNeeded
            when QtyNeeded + (i.QtyInventory - sum(s.QtyNeeded) over (partition by s.Part order by s.Part, s.ShipmentNumber)) > 0 
                then QtyNeeded + (i.QtyInventory - sum(s.QtyNeeded) over (partition by s.Part order by s.Part, s.ShipmentNumber))
            else 0
        end as InventoryUsed
        ,case 
                when i.QtyInventory - sum(s.QtyNeeded) over (partition by s.Part order by s.Part, s.ShipmentNumber) > 0 
                    then 0
                when i.QtyInventory - sum(s.QtyNeeded) over (partition by s.Part order by s.Part, s.ShipmentNumber) < 0 
                    then (i.QtyInventory - (sum(s.QtyNeeded) over (partition by s.Part order by s.Part, s.ShipmentNumber))) * - 1 
        end as QtyToProduce
        ,row_number() over (partition by s.Part order by s.Part, s.ShipmentNumber) as RN
    from
        @ShipmentSchedule s
        inner join
        @Inventory i on i.Part = s.Part)

select
    c.Part
    ,c.ShipmentNumber
    ,c.QtyNeeded
    ,c.InventoryUsed
    ,ISNULL(c.QtyToProduce - lag(QtyToProduce) over (partition by Part order by Part, ShipmentNumber),0) as QtyToProduce
    --,ISNULL(c.QtyToProduce - (select top 1 QtyToProduce from cte where c.RN -1 = RN  and c.Part = Part order by rn desc),0) as QtyToProduce --use this version to avoid using LAG
from    
    cte c

<强>结果

/*Running Total*/

+------+----------------+-----------+---------------+--------------+
| Part | ShipmentNumber | QtyNeeded | InventoryUsed | QtyToProduce |
+------+----------------+-----------+---------------+--------------+
|    1 |              1 |        30 |            30 |            0 |
|    1 |              2 |        30 |            10 |           20 |
|    1 |              3 |        30 |             0 |           50 |
|    2 |              1 |        40 |            40 |            0 |
|    2 |              2 |        40 |            10 |           30 |
+------+----------------+-----------+---------------+--------------+


/*CTE for each shipment*/

 +------+----------------+-----------+---------------+--------------+
| Part | ShipmentNumber | QtyNeeded | InventoryUsed | QtyToProduce |
+------+----------------+-----------+---------------+--------------+
|    1 |              1 |        30 |            30 |            0 |
|    1 |              2 |        30 |            10 |           20 |
|    1 |              3 |        30 |             0 |           30 |
|    2 |              1 |        40 |            40 |            0 |
|    2 |              2 |        40 |            10 |           30 |
+------+----------------+-----------+---------------+--------------+