在更新查询中使用多个连接是最优的吗?



我的更新查询检查列" 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

目标:

<表类>IDnamnmiddlename房屋日期tbody><<tr>1演示你好2空2以及接下来测试4空3demo3test15空

我推荐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列。

查找sourcehouses列中值为NULL的所有行。然后更新target中具有源行IDs的所有行。

我更喜欢用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();

要有效地找到sourcehouses列中值为NULL的行,您应该创建一个索引,如下所示:

CREATE INDEX IX_Houses ON Source
(
Houses
);

我假设ID是一个具有集群唯一索引的主键,因此ID将隐式地包含在IX_Houses索引中。

最新更新