次の初期データを想定しました: 製品:
PRODUCTID QUANTITY
1 10
2 210
3 0
ショッピングカート:
CARTID PRODUCTID QUANTITY DATEADDED
21 1 3 2012-11-20
24 1 1 2012-11-19
22 2 2 2012-11-25
23 3 3 2012-11-20
次の出力が得られます。
製品:
PRODUCTID QUANTITY
1 14
2 210
3 3
Products のすべての行で、Quantity が "x" 回更新されます。ここで、"x" は、ShoppingCart の一致する行の数です。ただし、反復ごとに「Products.Quantity」が保持する値は初期値であるため、最終的な結果は、Products.Quantity の初期値と、ShoppingCart で最後に一致したレコードの Quantity 値を加算したものになります。
たとえば、上記のデータセットでは、次の同等のアクションが製品 1 のデータベースで発生します。
UPDATE Products SET Quantity = 10 + 1 WHERE ProductId = 1;
UPDATE Products SET Quantity = 10 + 3 WHERE ProductId = 1;
したがって、最終的な値は 13 であり、予想される 14 ではありません。基本的に、INNER JOIN で評価された最後の行が優先され、残りは事実上無視されます。
これを回避するには、set コマンドを実行する前にデータを集約する必要があります。以下がうまくいくと思います。インライン ビューで各製品の期限切れの数量をすべて合計し、その値を更新に使用しています。
UPDATE Products
SET Products.Quantity = Products.Quantity + Expired.Quantity
FROM Products
INNER JOIN (SELECT S.ProductId, SUM(S.Quantity) AS Quantity
FROM ShoppingCart S
WHERE S.DateAdded < GETDATE()- 7
GROUP BY S.ProductId) AS Expired
ON Expired.ProductID = Products.ProductID
これをテストするためにSQL Fiddleを使用しました。