CTE 不更新所有选定的行

CTE not updating all the selected rows

我正在尝试对库存实施 FIFO。

我有以下 table 与库存相关:

Lot:
ID,SiteID,WHID,BatchID,Qty,Amount,QtyRemaning,AmountRemaning,LastQtyOut,DimComb, . . .

Dispatch Note:
ID,ProductID,SiteID,WHID,Quantity,DimComb, . . .

我有一个查询,它计算累积总和并根据 FIFO 出库:

;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 中有不同的 Quantity 和不同的 DimComb,CTE 在 select 上显示以下结果:

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           |

但问题是,它只更新 Lot table 第一行的 DNQty 2。

我也评论了 WHERE 子句,但它也不起作用。 我认为它不会用第二行(即 DNQty 3 的行)更新 Lot table,因为这两行都引用 Lot table 中的同一行(即 LotID 783)。

如有任何帮助,我们将不胜感激。

I think its not updating the Lot table with 2nd row (.i.e. the row with DNQty 3) because the both rows refer to same row in Lot table (.i.e LotID 783).

是的,正是这样。

您的示例可以简化为:

create table #tmpTblDN (DNQty int, DNProductID int);
insert into #tmpTblDN values (2, 14), (3, 14);

create table #lot (LotsProductID int, 
                   LotID int, 
                   QtyRemaning int, 
                   UnitCost int, 
                   LotQty int, 
                   AmountRemaning int,
                   LastQtyOut int, 
                   CumulativeSum int);
insert into #lot values
(14, 783, 100, 3, 100, 300, NULL, 100)  


;WITH CTE AS 
(
    SELECT *
    FROM 
        #tmpTblDN DN
    RIGHT JOIN
        #lot lot
           on dn.DNProductID = lot.LotsProductID
)

UPDATE 
    CTE
SET
--select *,
    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 

FROM CTE
WHERE CumulativeSum <= QtyRemaning + DNQty

所以你清楚地看到你的第一个 table 包含 2 行,但是你对第二个 table (通过 cte)做了一个 update 只有一行。

可以在 "Updating Data Based on Data From Other Tables":

部分下的 BOL 文章 UPDATE (Transact-SQL) 中找到对此的解释

In this case I want to update Lot with ID 783 by subtracting DNQty 2 and 3 (i.e. In first update LotQtyRemaning should have value of 98, and after second update it should have value of 95).

这意味着你想 update 你的 Lot table 通过使用 DNQty 的 sum,所以首先你应该编写一个聚合查询来计算 sum(DNQty),这样你保证每个 LotsProductID 将只有一个对应的 DNProductID (在我的例子中。在你的例子中你应该 group by 你在你的 join 然后使用所有字段 join 将您的聚合结果 Lot table)

update lot
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 
from #lot lot
     join (select DNProductID, sum(DNQty) as DNQty
           from #tmpTblDN
           group by DNProductID) dn
             on dn.DNProductID = lot.LotsProductID