我想从一个表中返回多个行,其总和取决于另一个表中某行的值:
场景:特定商品数量的销售订单。该项目位于多个Bin位置。商店需要定向到最古老的材料。
我可以创建一个查询,列出Bin,bin中的数量并按年龄列出它们(最老到最年轻) - 到目前为止都很好,但是说订单是100个单位,有50个左右的单位在每个垃圾箱里有40个垃圾箱,然后我不想列出所有的垃圾箱,只列出最旧的垃圾箱 - 只需足以完成订单。
我该怎么做?
根据要求提供更多信息 DB = MS SQL 2016 样本数据: 以下是显示Bin的特定项目的数据,该bin中的数量和老化日期:
Bin#,Qty,Date
1,40,2018-05-15
3,45,2018-05-15
8,45,2018-02-10
12,45,2017-11-11
13,45,2018-02-10
15,45,2017-09-02
18,20,2017-09-02
销售订单是100个这样的项目,我们想选择FIFO(先进先出),所以我想要返回的结果是:
18,20,2017-09-02
15,45,2017-09-02
12,45,2017-11-11
这三个箱子共包含110个单位,足以满足销售订单。请注意,订单是日期,然后是数量
目前的实际查询是:
select
[OrderHed].[OrderNum] as [OrderHed_OrderNum],
[OrderRel].[OrderLine] as [OrderRel_OrderLine],
[Part].[PartNum] as [Part_PartNum],
[Part].[PartDescription] as [Part_PartDescription],
[OrderRel].[OurReqQty] as [OrderRel_OurReqQty],
[PartBin].[BinNum] as [PartBin_BinNum],
[PartBin].[OnhandQty] as [PartBin_OnhandQty],
[PartLot].[FirstRefDate] as [PartLot_FirstRefDate]
from Erp.OrderHed as OrderHed
inner join Erp.OrderDtl as OrderDtl on
OrderHed.Company = OrderDtl.Company
and OrderHed.OrderNum = OrderDtl.OrderNum
inner join Erp.OrderRel as OrderRel on
OrderDtl.Company = OrderRel.Company
and OrderDtl.OrderNum = OrderRel.OrderNum
and OrderDtl.OrderLine = OrderRel.OrderLine
and ( OrderRel.OpenRelease = True )
left outer join Erp.PartBin as PartBin on
OrderRel.Company = PartBin.Company
and OrderRel.WarehouseCode = PartBin.WarehouseCode
and ( not PartBin.BinNum like 'Q' )
inner join Erp.Part as Part on
OrderDtl.Company = Part.Company
and OrderDtl.PartNum = Part.PartNum
right outer join Erp.Part as Part
and
PartBin.Company = Part.Company
and PartBin.PartNum = Part.PartNum
inner join Erp.PartLot as PartLot on
PartBin.Company = PartLot.Company
and PartBin.PartNum = PartLot.PartNum
and PartBin.LotNum = PartLot.LotNum
where (OrderHed.OrderNum = @SalesOrder)
order by OrderDtl.OrderLine, PartLot.FirstRefDate, PartBin.OnhandQty
答案 0 :(得分:0)
您可以选择日期小于或等于日期小于或等于的所有垃圾箱数量总和大于或等于目标数量的最小日期(例如50) )。
SELECT *
FROM bin b
WHERE b.date <= (SELECT min(bb.date)
FROM bin bb
WHERE (SELECT sum(bbb.qty)
FROM bin bbb
WHERE bbb.date <= bb.date) >= 50)
ORDER BY b.date,
b.bin#;
然而,这种方法可能包括比必要的更多的箱子。如果从最年轻的日期开始有更多的垃圾箱,那么只需要满足目标数量,所有垃圾箱都会被包含在内。因此,为订单挑选物品的人必须从这些垃圾箱中进行选择。但至少FIFO规则是这样保留的,而且无论如何都必须对物品进行计数,而不能盲目地从退回的箱子中挑选。
SQL Fiddle(注意,我添加了bin 20来演示上述问题。)
如果您按日期订购所有垃圾箱,可以规避我提到的关于1.的问题。然后,与日期不会有重复的值。您可以在CTE中使用ROW_NUMBER()
来引入此号码。然后从CTE中选择与1中相同的逻辑,但应用于行号而不是日期。
WITH cte
AS
(
SELECT ROW_NUMBER() OVER (ORDER BY b.date) row#,
b.*
FROM bin b
)
SELECT *
FROM cte c
WHERE c.row# <= (SELECT min(cc.row#)
FROM cte cc
WHERE (SELECT sum(ccc.qty)
FROM cte ccc
WHERE ccc.row# <= cc.row#) >= 50)
ORDER BY c.date,
c.bin#;
SQL Fiddle(请注意,我再次添加了bin 20来证明,解决了1.中提到的问题。)