【发布时间】:2022-08-19 01:48:31
【问题描述】:
我知道这不应该发生在数据库中,但它发生了,我们必须处理它。如果新行不存在,我们需要根据另一个表中的值将它们插入到表中。这很容易(只需执行 LEFT JOIN 并检查第一个表中的 NULL 值)。但是......连接不是很直接,我们需要在 2 个条件下使用 OR 而不是 AND 搜索第一个表。所以基本上如果它在两个属性中的任何一个上找到匹配项,我们认为第一个表中的对应行存在,我们不必插入新的。如果这两个属性中的任何一个都没有匹配项,那么我们将其视为新行。我们可以在 LEFT JOIN 语句中使用 OR 条件,但据我了解,它会进行全表扫描,并且查询需要很长时间才能完成,即使它产生了正确的结果。我们也不能使用 UNION,因为它不会给我们想要的东西。 为简单起见,请考虑以下场景(我们需要将数据插入到 tableA 中)。
If(OBJECT_ID(\'tempdb..#tableA\') Is Not Null) Begin
Drop Table #tableA End
If(OBJECT_ID(\'tempdb..#tableB\') Is Not Null) Begin
Drop Table #tableB End
create table #tableA ( email nvarchar(50), id int )
create table #tableB ( email nvarchar(50), id int )
insert into #tableA (email, id) values (\'123@abc.com\', 1), (\'456@abc.com\', 2), (\'789@abc.com\', 3), (\'012@abc.com\', 4)
insert into #tableB (email, id) values (\'234@abc.com\', 1), (\'456@abc.com\', 2), (\'567@abc.com\', 3), (\'012@abc.com\', 4), (\'345@abc.com\', 5)
--THIS QUERY IS CORRECTLY RETURNING 1 RECORD
select B.email, B.id
from #tableB B
left join #tableA A on A.email = B.email or B.id = A.id
where A.id is null
--THIS QUERY IS INCORRECTLY RETURNING 3 RECORDS SINCE THERE ARE ALREADY RECORDS WITH ID\'s 1 & 3 in tableA though the email addresses of these records don\'t match
select B.email, B.id
from #tableB B
left join #tableA A on A.email = B.email
where A.id is null
union
select B.email, B.id
from #tableB B
left join #tableA A on B.id = A.id
where A.id is null
If(OBJECT_ID(\'tempdb..#tableA\') Is Not Null) Begin
Drop Table #tableA End
If(OBJECT_ID(\'tempdb..#tableB\') Is Not Null) Begin
Drop Table #tableB End
第一个查询工作正常,只返回 1 条记录,但表大小只有几条记录,它在 1 秒内完成。当 2 个表有数千条记录时,查询可能需要 10 分钟才能完成。第二个查询当然会返回我们不想插入的记录,因为我们认为它们存在。有没有办法优化这个查询,所以它需要一个可接受的时间来完成?
-
您的查询对我来说是正确的。如果您没有获得所需的性能,我认为您只需要考虑添加适当的索引即可。
-
\“当 2 个表有数千个或记录时,查询可能需要 10 分钟才能完成。\”这是假设还是您检查过?数以千计的记录实际上并没有那么多,我不希望这样的查询执行得那么糟糕(尤其是如果存在适当的索引)。也许
EXISTS提供了更好的性能,但你确实需要检查执行计划 -
是的,我在 JOIN 中使用 OR 对其进行了测试,大约需要 10 分钟。表 A 有超过 50,000 条记录,表 B 有近 20,000 条记录。如果我仅在 1 个条件下从 JOIN 和 JOIN 中删除 OR,则需要几秒钟。不幸的是,我们正在处理 SaaS DB,无法在其中创建索引。
标签: sql sql-server left-join union