我正在尝试自动执行将库存分配给未来货件的手动功能,以确定何时需要再次生产零件。所以在一个简单的例子中:
稍微清理一下这个例子:
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 :(得分: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 |
+------+----------------+-----------+---------------+--------------+