我正在尝试使用MERGE
语句从表中插入或删除行,但我只想对这些行的一个子集进行操作。的文档MERGE
有一个措辞非常强烈的警告:
仅指定目标表中用于匹配目的的列很重要。也就是说,指定目标表中与源表的相应列进行比较的列。不要试图通过在 ON 子句中过滤掉目标表中的行来提高查询性能,例如通过指定 AND NOT target_table.column_x = value。这样做可能会返回意外和不正确的结果。
但这正是我必须做的事情才能完成我的MERGE
工作。
我拥有的数据是一个标准的项目到类别的多对多连接表(例如,哪些项目包含在哪些类别中),如下所示:
CategoryId ItemId
========== ======
1 1
1 2
1 3
2 1
2 3
3 5
3 6
4 5
Run Code Online (Sandbox Code Playgroud)
我需要做的是用新的项目列表有效地替换特定类别中的所有行。我最初的尝试是这样的:
MERGE INTO CategoryItem AS TARGET
USING (
SELECT ItemId FROM SomeExternalDataSource WHERE CategoryId = 2
) AS SOURCE
ON SOURCE.ItemId = TARGET.ItemId AND TARGET.CategoryId = 2
WHEN NOT MATCHED BY TARGET THEN
INSERT ( CategoryId, ItemId )
VALUES ( 2, ItemId ) …
Run Code Online (Sandbox Code Playgroud) 我正在尝试在两个表之间进行单列合并。第一个表 ( VisitorSession
) 有 40,000,000 行。第二个 ( ShoppingCart
) 有 9,000,000 行。
在我的开发环境中,查询只需不到 8 分钟。但是在生产环境中,它应该占用更少(更强大的机器)。但是,我预计该查询至少需要 2 分钟才能在生产中运行。我知道这个查询会导致开发环境中的其他开发人员超时,这意味着它很容易导致客户超时。是否有更安全和/或更快的方法来执行此查询?
declare @dt datetime = cast(dateadd(month, -6, getdate()) as date);
merge ShoppingCart as TargetTable -- 07:55 to complete in Dev
using
(
select * from -- 04:55 to run select, resulting in 12,727,927 rows in Dev
(
select
visitorid -- int, not null, foreign key
,useripaddress -- varchar(55), null
,row_number() over
(partition by visitorid order by createdate desc) as [row]
from VisitorSession (nolock) …
Run Code Online (Sandbox Code Playgroud)