Sql CTE-减少库存量
我希望用MSSQL中的CTE解决以下问题,但我遇到了麻烦 这是我的问题 订单表:Sql CTE-减少库存量,sql,sql-server,common-table-expression,Sql,Sql Server,Common Table Expression,我希望用MSSQL中的CTE解决以下问题,但我遇到了麻烦 这是我的问题 订单表: OrderID Item Quantity ------------------------ 1 pen 80 2 pen 30 3 pen 25 库存表: Inv ID Lot Item Quantity --------------------------- 1 001 pen 100 2
OrderID Item Quantity
------------------------
1 pen 80
2 pen 30
3 pen 25
库存表:
Inv ID Lot Item Quantity
---------------------------
1 001 pen 100
2 002 pen 20
3 003 pen 30
我需要做的是处理订单,以便第一批订单来自标段1,第二批订单来自标段1和标段2,第三批订单来自标段2和标段3
我需要知道什么样的订单来自哪个批次,这意味着我不能把订单分组
所以基本上我需要类似的东西:
OrderID Item QuantityOrdered Lot QuantityFromLot
--------------------------------------------------
1 pen 80 001 80
2 pen 30 001 20
2 pen 30 002 10
3 pen 25 002 10
3 pen 25 003 15
有没有办法用CTE做到这一点?如果没有,您会推荐什么?对于此类问题,C或其他应用层解决方案可能是最好的解决方法 但这是可以在SQL中实现的,尽管它有点复杂 递归CTE的第一部分将取OrderID=1和InvID=1并对其进行计算,结果是LeftInLot>0或LeftToServe>0 第二部分现在需要基于第一部分的结果的两种不同的逻辑,这是通过子查询来完成的,子查询同时获取下一批和下一项,并使用一堆案例来确定要使用哪一个,再使用几个案例来为下一次递归继续提供准确的数据 它看起来是这样的:
;WITH CTE_Orders AS
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY Item ORDER BY OrderID) AS RN
FROM dbo.Orders
)
, CTE_Inventory AS
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY Item ORDER BY InvID) AS RN
FROM dbo.Inventory
)
, CTE AS
(
SELECT o.RN AS OrderRN,
inv.RN AS InvRN,
OrderID ,
o.Item ,
o.Quantity AS OrderedQuantity ,
InvID ,
Lot ,
inv.Quantity AS InvQuantity,
CASE WHEN inv.Quantity - o.Quantity > 0 THEN o.Quantity ELSE inv.Quantity END AS ServedQuantity ,
CASE WHEN inv.Quantity - o.Quantity > 0 THEN 0 ELSE o.Quantity - inv.Quantity END AS LeftToServe,
CASE WHEN inv.Quantity - o.Quantity > 0 THEN inv.Quantity - o.Quantity ELSE 0 END AS LeftInLot
FROM CTE_Orders o
INNER JOIN CTE_Inventory inv ON o.Item = inv.Item
--WHERE OrderID = 1 AND InvID = 1
WHERE o.RN =1 AND inv.RN = 1
UNION ALL
SELECT CASE WHEN c1.LeftInLot <=0 THEN c1.OrderRN ELSE c2.OrderRN END AS OrderRN
,CASE WHEN c1.LeftInLot <=0 THEN c2.InvRN ELSE c1.InvRN END AS InvRN
,CASE WHEN c1.LeftInLot <=0 THEN c1.OrderID ELSE c2.OrderID END AS OrderID
,CASE WHEN c1.LeftInLot <=0 THEN c1.Item ELSE c2.Item END AS Item
,CASE WHEN c1.LeftInLot <=0 THEN c1.OrderedQuantity ELSE c2.OrderedQuantity END AS OrderedQuantity
,CASE WHEN c1.LeftInLot <=0 THEN c2.InvID ELSE c1.InvID END AS InvID
,CASE WHEN c1.LeftInLot <=0 THEN c2.Lot ELSE c1.Lot END AS Lot
,CASE WHEN c1.LeftInLot <=0 THEN c2.InvQuantity ELSE c1.LeftInLot END AS InvQuantity
,CASE WHEN CASE WHEN c1.LeftInLot <=0 THEN c2.InvQuantity ELSE c1.LeftInLot END - CASE WHEN c1.LeftInLot <=0 THEN c1.LeftToServe ELSE c2.OrderedQuantity END > 0
THEN CASE WHEN c1.LeftInLot <=0 THEN c1.LeftToServe ELSE c2.OrderedQuantity END
ELSE CASE WHEN c1.LeftInLot <=0 THEN c2.InvQuantity ELSE c1.LeftInLot END
END AS ServedQuantity
,CASE WHEN CASE WHEN c1.LeftInLot <=0 THEN c2.InvQuantity ELSE c1.LeftInLot END - CASE WHEN c1.LeftInLot <=0 THEN c1.LeftToServe ELSE c2.OrderedQuantity END > 0
THEN 0
ELSE CASE WHEN c1.LeftInLot <=0 THEN c1.LeftToServe ELSE c2.OrderedQuantity END - CASE WHEN c1.LeftInLot <=0 THEN c2.InvQuantity ELSE c1.LeftInLot END
END AS LeftToServe
,CASE WHEN CASE WHEN c1.LeftInLot <=0 THEN c2.InvQuantity ELSE c1.LeftInLot END - CASE WHEN c1.LeftInLot <=0 THEN c1.LeftToServe ELSE c2.OrderedQuantity END > 0
THEN CASE WHEN c1.LeftInLot <=0 THEN c2.InvQuantity ELSE c1.LeftInLot END - CASE WHEN c1.LeftInLot <=0 THEN c1.LeftToServe ELSE c2.OrderedQuantity END
ELSE 0
END AS LeftInLot
FROM CTE c1
INNER JOIN
(
SELECT o2.RN AS OrderRN,
inv2.RN AS InvRN,
InvID ,
Lot ,
inv2.Item ,
inv2.Quantity AS InvQuantity,
OrderID ,
o2.Quantity AS OrderedQuantity
FROM
CTE_Inventory inv2
INNER JOIN CTE_Orders o2 ON inv2.Item = o2.Item
) c2
ON c1.Item = c2.Item AND
((c2.InvRN = c1.InvRN + 1 AND c2.OrderRN = c1.OrderRN AND c1.LeftInLot <= 0 ) OR (c2.OrderRN = c1.OrderRN + 1 AND c2.InvRN = c1.InvRN AND c1.LeftInLot>0))
)
SELECT * FROM CTE
ORDER BY item,OrderID
PS:因为您不能真正相信OrderID和InvID是没有任何间隙的连续值——就像我的示例假设的c2.OrderID=c1.OrderID+1一样,应该对行数进行额外的复杂化。固定的
编辑:
更新了用于处理多个项目的解决方案。开始时还有两个CTE用于计算为项目划分的行数,并在联接中使用这些行数而不是ID。Hi,感谢您的回复。这是一个绝妙的解决方案。由于某些原因,我无法添加更多项目。它只会为我提供第一项“笔”的解决方案。你怎么认为?我同意在应用程序逻辑中这样做会更好,但不幸的是我仅限于sql。可能在某个地方缺少一些连接或条件。。。我会看看我是否能找到它…@user2417191好的,我已经更新了解决方案来处理多个项目。开始时还有两个CTE用于计算为项目划分的行数,并在联接中使用这些行数而不是ID。另外,在结尾处添加c1.item=c2.item优秀的解决方案。非常感谢!