使用联接从其他表的值逐行更新SQL Server表

时间:2018-09-13 12:51:30

标签: sql sql-server join sql-update

我有3张桌子。

Table Product

Product_ID | Review_date |
1          | 01/01/2018    |
2          | 01/01/2018    |
3          | 01/01/2018    |
4          | 01/01/2018    |

Table Inventory
Inventory_ID  | Product_ID  | Location_ID
1             |        2    | 1    |
2             |        2    | 3    |
3             |        3    | 4    |
4             |        1    | 4    |

Table Location
Location_ID| Review_date |
1          | 04/02/2018    |
2          | 06/03/2018    |
3          | 01/05/2018    |
4          | 08/28/2018    |

更新 产品表中的产品信息集。库存表包含有关产品可用地点的信息。一个产品可以有多个库存,而一个产品可以没有库存。位置表具有所有可能位置的唯一列表。位置表中的审核日期通常会更新。

我想为每个产品ID更新产品表中的评论日期,并从位置表中为每个产品ID选择max(review_date)。因为产品可以具有多个库存和分配给它的位置。我要更新产品位置的最近日期。

预期结果

餐桌产品

Product_ID | Review_date |
1          | 08/28/2018    |  this prod id in inventory has loc id 4. 
2          | 04/02/2018    |  two inv records for the product so max date
3          | 08/28/2018    |
4          | 01/01/2018    |  no inv record. so leave it as such


UPDATE  P
SET     P.review_date = L.Inventory_review_date
FROM    Product AS P
CROSS APPLY
        (
        select  top 1 inventory_review_Date
        from    Location as L, Inventory as I, PRODUCT as P
        where   L.Location_ID = I.Inventory_ID and P.Product_ID = I.Product_ID
        order by
                L.Inventory_Review_date desc
        ) as L  

我以不同的方式尝试了类似的方法,但是我似乎没有得到。任何帮助表示赞赏。 TIA

3 个答案:

答案 0 :(得分:1)

您似乎在将位置表加入到两个不同信息的库存表中。 (位置ID和产品ID)如果“库存”表中的LocationID是位置ID而不是日期(如您的示例所示),请尝试此操作。 (未测试)

UPDATE  P
SET     P.review_date = L.Inventory_review_date
FROM    Product AS P
CROSS APPLY
        (
        select  top 1 inventory_review_Date
        from    Location as L, Inventory as I, PRODUCT as P
        where   L.Location_ID = I.Location_ID and P.Product_ID = I.Product_ID
        order by
                L.Inventory_Review_date desc
        ) as L  

此外,我认为您将必须按Location_ID进行订购才能将所有位置汇总在一起,然后选择最上层日期。我还没有尝试过,所以TOP的聚合函数可能不允许您这样做。

答案 1 :(得分:1)

如果您以此方式看待。 您有产品表,并且有库存和位置的组合。您可以使用子查询来执行此操作,也可以尝试使用公用表表达式MS CTE DOCS

来解决该问题。

这看起来像

  • 弄清楚库存中任何产品的最后审核日期。
  • 更新产品中的那些产品

使用CTE就像。

WITH inv_loc_cte AS
(
Select i.Product_id, max(l.Review_date)
    from Inventory i 
    inner join [Location] l on i.Location_id = i.Location_id
    Group by i.Product_id
)
UPDATE p
SET Review_date = c.Review_date
FROM Product p
INNER JOIN inv_loc_cte c on p.Product_id = c.Product_id

答案 2 :(得分:0)

首先,从不FROM子句中使用逗号。 始终使用正确的,明确的,标准 JOIN语法。

第二,您可以使用APPLY进行此操作。问题是Product表的重复。您需要一个相关条件,此功能才能按预期工作。但是子查询和要更新的表之间没有关联,因此所有子查询都具有相同的值。

所以:

UPDATE P
    SET review_date = L.Inventory_review_date
    FROM Product P CROSS APPLY
         (SELECT TOP (1) L.inventory_review_Date
          FROM Location L JOIN
               Inventory I
               ON L.Location_ID = I.Inventory_ID 
          WHERE P.Product_ID = I.Product_ID
          ORDER BY L.Inventory_Review_date DESC
        ) L;

您也可以使用GROUP BY进行此操作。如果索引正确,很有可能APPLY会更快。