我们的数据库是SQL Server2014。我将简化示例以解释我的问题。
TableA
具有列:
CustomerID (primary key), LatestOrderedItem, LatestOrderDate
TableB
具有列:
OrderID, CustomerID, OrderedItem, PurchaseDate
我想用LatestOrderedItem
(基于购买日期)的客户的最新/最近订单更新LatestOrderDate
的{{1}}和TableA
。
对此最好/最有效的更新说明是什么? (实际上,在我们的情况下,两个表都有数百万条记录。)
我尝试过的方法,但是仍然很慢:
方法1:
TableB
方法2:
UPDATE a
SET LatestOrderedItem = (SELECT TOP 1
OrderedItem
FROM TableB
WHERE CustomerID = a.CustomerID
ORDER BY PurchaseDate DESC),
LatestOrderDate = (SELECT TOP 1
PurchaseDate
FROM TableB
WHERE CustomerID = a.CustomerID
ORDER BY PurchaseDate DESC)
FROM TableA a;
答案 0 :(得分:0)
尝试使用CROSS APPLY
和TOP
。
UPDATE a SET
LatestOrderedItem = c.OrderedItem,
LatestOrderDate = c.PurchaseDate
FROM
TableA a
CROSS APPLY (
SELECT TOP 1
b.OrderedItem,
b.PurchaseDate
FROM
TableB b
WHERE
a.CustomerID = b.CustomerID
ORDER BY
b.PurchaseDate DESC
) AS C
以下索引是此更新性能的关键。可以选择include OrderedItem
列,或创建索引clustered,尽管这样做有副作用。
CREATE NONCLUSTERED INDEX NCI_TableB_CustomerID_PurchaseDate ON TableB (CustomerID, PurchaseDate) -- INCLUDE (OrderedItem)
PD :请阅读Larnu的评论,因为将这些数据存储在表中暗示着反规范化,并且从长远来看会带来麻烦。
答案 1 :(得分:0)
另一个选项是派生表中的窗口函数。
update a
set a.LatestOrderedItem = b.OrderedItem
,a.LatestOrderDate = b.PurchaseDate
from TableA a
inner join
(select CustomerID, OrderedItem, PurchaseDate,
row_number() over (partition by CustomerID order by PurchaseDate desc) as seq
from TableB) on b.CustomerID = a.CustomerID and b.seq = 1
答案 2 :(得分:0)
窗口功能,一次扫描要更新的两列:
UPDATE a
SET a.LatestOrderedItem = b.OrderedItem,
a.LatestOrderDate = b.PurchaseDate
FROM TableA a
JOIN
(
SELECT CustomerID,
OrderedItem,
PurchaseDate,
ROW_NUMBER() OVER (PARTITION BY CustomerID ORDER BY PurchaseDate DESC) RN
FROM TableB
WHERE CustomerID = a.CustomerID
) b
ON a.CustomerID = b.CustomerID
AND b.RN = 1;