我的更新查询检查列" Houses "在源表的任何行中是否为空,方法是在目标&源表(检查查询1)。在这种情况下,列Houses为空表示该行已经过期;因此,我需要使目标表中的行id过期,并设置过期日期。查询工作得很好,但我想知道它是否可以改进;我是SQL新手,所以我不知道使用两个连接是否是实现我想要的结果的最佳方式。我的更新查询稍后将用于数百万行。还没有列被索引。
查询:
(Query one)
Update t
set valid_date = GETDATE()
From Target T
JOIN SOURCE S ON S.ID = T.ID
LEFT JOIN SOURCE S2 ON S2.Houses = t.Houses
WHERE S2.Houses is null
目标:
我推荐exists
:
update t
set valid_date = getdate()
from target t
where exists (select 1 from source s where s.id = t.id and s.houses is null)
请注意,您的原始查询并不完全符合您的要求。不能区分不存在的源行和存在且houses
列为null
的源行。在您的示例中,它将更新行2
,这似乎不是您想要的。你需要一个INNER JOIN
而不是LEFT JOIN
。
对于EXISTS
,您需要在source(id, houses)
上建立索引,以便子查询可以有效地执行target
行。这个索引对于JOIN
来说可能也是值得的。
我不明白你为什么需要加入houses
列。
查找source
中houses
列中值为NULL的所有行。然后更新target
中具有源行ID
s的所有行。
我更喜欢用cte来写这些复杂的更新。对我来说它看起来更容易读。
WITH
CTE
AS
(
SELECT
Target.ID
,Target.Date
FROM
Source
INNER JOIN Target ON Target.ID = Source.ID
WHERE Source.Houses IS NULL
)
UPDATE CTE
SET Date = GETDATE();
要有效地找到source
中houses
列中值为NULL的行,您应该创建一个索引,如下所示:
CREATE INDEX IX_Houses ON Source
(
Houses
);
我假设ID
是一个具有集群唯一索引的主键,因此ID
将隐式地包含在IX_Houses
索引中。