如何使用另一个表中的值更新表中的多个行?

时间:2012-11-28 01:11:37

标签: sql-server sql-update

UPDATE Products 
SET Products.Quantity = Products.Quantity + ShoppingCart.Quantity
FROM Products INNER JOIN ShoppingCart
    ON ShoppingCart.ProductID = Products.ProductID 
WHERE ShoppingCart.DateAdded < GETDATE()- 7
DELETE FROM ShoppingCart
WHERE DateAdded < GETDATE()- 7 

并且此查询需要完成此任务:

ShoppingCart中添加的超过7天的产品将被删除,其数量将返回到该产品的可用数量以进行销售。但问题是只有第一个产品的数量会在Products.Quantity字段中重新添加。其余的不计算并添加回Products表中。

1 个答案:

答案 0 :(得分:0)

我假设了以下初始数据: 产品:

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

正在发生的事情是,对于产品中的每一行,数量都会更新“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来测试它。