2017-04-07 39 views
2

我正在尝试自动执行将库存分配到未来货件的手动功能,以确定何时需要再次生产零件。因此,在一个简单的例子:将库存分配到即将发货的SQL查询

清洁例如一点点:

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 
+0

你的样品是不明确的..你怎么得到的结果你显示??? – scaisEdge

+1

这里是一个开始的好地方。 http://spaghettidba.com/2015/04/24/how-to-post-at-sql-question-on-a-public-forum/ –

回答

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 | 
+------+----------------+-----------+---------------+--------------+ 
+0

谢谢,我刚刚完成了这项工作,并有一个非常类似的解决方案。一个问题:通过使用稍微不同的情况,我能够在不使用cte的情况下获得QtyToProduce: 当(QtyInventory-RunTot)* -1>数量需求 然后数量需求 当(QtyInventory - RunTot)* -1> 0 那么(QtyInventory - RunTot)* -1 Else 0 End由于Bal对CTE有优势吗? –

+0

看起来你做了一个正在运行的总列 - 你是否这样做,并更新你的表? – scsimon

+0

我使用了2个查询,第一次运行运行总数,第二次运行了Case语句 –