【发布时间】:2019-11-14 19:53:48
【问题描述】:
我正在尝试在 Inventory 上实现 FIFO。
我有以下与库存相关的表格:
Lot:
ID,SiteID,WHID,BatchID,Qty,Amount,QtyRemaning,AmountRemaning,LastQtyOut,DimComb, . . .
Dispatch Note:
ID,ProductID,SiteID,WHID,Quantity,DimComb, . . .
我有一个查询,它根据 FIFO 计算累计和 OUT 库存:
;WITH CTE AS (
SELECT
DN.fldQty as DNQty,
DN.fldProductID as DNProductID,
lot.fldProductID as LotsProductID,
lot.fldID as LotID,
lot.fldQtyRemaning as QtyRemaning,
lot.fldUnitCost as UnitCost,
lot.fldQty as LotQty,
lot.fldAmountRemaning as AmountRemaning,
lot.fldLastQtyOut as LastQtyOut,
lot.fldLastUpdateRefDoc as fldLastUpdateRefDoc,
lot.fldLastUpdateRefDocNum as fldLastUpdateRefDocNum,
DN.DimComb as DNDimComb,
lot.DimComb,
CumulativeSum= SUM(lot.fldQtyRemaning)
OVER
(PARTITION BY
DN.DimComb,
lot.fldProductID,
lot.fldSiteID,
lot.fldWHID,
lot.fldLocationID,
lot.fldPalletID--,
--lot.fldBatchID
ORDER BY lot.fldID ROWS UNBOUNDED PRECEDING)
FROM
#tmpTblDN DN
RIGHT JOIN
lot lot
ON
--lot.fldRefDocNum = tblGRNItems.fldGRNID AND
ISNULL(DN.fldProductID,0) = ISNULL(lot.fldProductID,0) AND
ISNULL(DN.fldSiteID,0) = ISNULL(lot.fldSiteID,0) AND
ISNULL(DN.fldWHID,0) = ISNULL(lot.fldWHID,0) AND
ISNULL(DN.fldLocationID,0) = ISNULL(lot.fldLocationID,0) AND
ISNULL(DN.fldPalletID,0) = ISNULL(lot.fldPalletID,0) --AND
--ISNULL(tblSIRItems.fldBatchID,0) = ISNULL(lot.fldBatchID,0)
WHERE
DN.fldDNID = @DNID
AND lot.fldQtyRemaning > 0
)
UPDATE
CTE
SET
QtyRemaning = CASE
WHEN (CumulativeSum - DNQty) < 0 AND DNProductID = LotsProductID THEN 0
WHEN (CumulativeSum - DNQty) BETWEEN 0 AND QtyRemaning AND DNProductID = LotsProductID THEN (CumulativeSum - DNQty)
ELSE QtyRemaning
END ,
LastQtyOut = CASE
WHEN (CumulativeSum - DNQty) < 0 AND DNProductID = LotsProductID THEN QtyRemaning
WHEN (CumulativeSum - DNQty) BETWEEN 0 AND QtyRemaning AND DNProductID = LotsProductID THEN
CASE WHEN LotQty = QtyRemaning THEN
(QtyRemaning - (CumulativeSum - DNQty))
ELSE
(CumulativeSum - (CumulativeSum - DNQty))
END
ELSE LastQtyOut
END ,
AmountRemaning = CASE
WHEN (CumulativeSum - DNQty) < 0 AND DNProductID = LotsProductID THEN AmountRemaning - (QtyRemaning * UnitCost)
WHEN (CumulativeSum - DNQty) BETWEEN 0 AND QtyRemaning AND DNProductID = LotsProductID THEN
CASE WHEN LotQty = QtyRemaning THEN
AmountRemaning - ((QtyRemaning - (CumulativeSum - DNQty)) * UnitCost)
ELSE
AmountRemaning - ((CumulativeSum - (CumulativeSum - DNQty)) * UnitCost)
END
ELSE AmountRemaning
END ,
fldDimComb = DNDimComb,
fldLastUpdateRefDoc = 'DispatchNote',
fldLastUpdateRefDocNum = @DNID
FROM CTE
WHERE CumulativeSum <= QtyRemaning + DNQty
现在我有相同的 ProductID 具有不同的数量和 DN 中不同的 DimComb 的情况,CTE 在选择时显示以下结果:
DNQty | DNProductID | LotsProductID | LotID | QtyRemaning | UnitCost | LotQty | AmountRemaning | LastQtyOut | CumulativeSum |
2 | 14 | 14 | 783 | 100 | 3 | 100 | 300 | NULL | 100 |
3 | 14 | 14 | 783 | 100 | 3 | 100 | 300 | NULL | 100 |
但问题是,它只用 DNQty 2 的第一行更新 Lot 表。
我还评论了 WHERE 子句,但它也不起作用。 我认为它没有用第二行(即 DNQty 3 的行)更新 Lot 表,因为这两行都引用 Lot 表中的同一行(即 LotID 783)。
任何帮助将不胜感激。
【问题讨论】:
-
非常怀疑是否有人会穿过这堵代码墙开始调试它。但是我看到由于使用 where 子句而隐式转换为内部连接的右连接 - 这绝不是一个好兆头。使用脚本或小提琴提供简化示例将鼓励其他人。
-
我在您的更新案例条件中看到:DNProductID =lotsProductID。但这并不像您在 CTE 中的连接那样考虑 NULL 值。那么,应该吗?还是您的 CTE 逻辑不一致且过于复杂?很大程度上取决于您的架构和表使用情况——只有您知道。
-
@SMor:感谢您花时间调查此事。我尽力提供尽可能多的信息来理解问题。对于 NULL check in update 语句,我已经在更新查询之前检查了 Lot 表的产品可用性。
-
你的问题是意大利面条代码,语法的格式和一致性也有一些不足之处!
标签: sql-server common-table-expression fifo