如果其中一个条件为真,我该如何执行JOIN?

时间:2014-12-29 21:55:40

标签: sql ms-access ms-access-2010

我的最终目标... SELECT来自qry1的所有字段,其中包含家庭电话,手机或工作电话匹配tbl2

这是我当前的SQL语法,它失败了。"失败意味着它在10-15分钟后没有完成执行,而个人在一两分钟内加入每个(独立)运行。

SELECT qry1.* FROM qry1 INNER JOIN tbl2 ON ((qry1.CellPhone = tbl2.CellPhone) OR (qry1.HomePhone = tbl2.HomePhone) OR (qry1.WorkPhone = tbl2.WorkPhone));

问题: 我的SQL语法有错误吗? 有没有更好的方法来完成我的任务? 如果只是单独运行3(Home,work,cell)JOIN查询,UNION它们,然后在必要时进行重复数据删除,对我来说更有意义吗?

4 个答案:

答案 0 :(得分:6)

如果个人快速加入工作,则复合OR条件可能很慢,因为它不能使用单个索引,而各个条件可以分别使用单个索引用于三个连接条件。因为它不能使用一个索引,所以它可能正在执行非索引顺序表扫描。 (您应该研究查询计划,以便了解优化程序实际执行的操作。)

鉴于单个查询的工作速度相当快,因此使用UNION会获得更好的性能(除非DBMS中的优化器有盲点):

SELECT qry1.* FROM qry1 INNER JOIN tbl2 ON qry1.CellPhone = tbl2.CellPhone
UNION
SELECT qry1.* FROM qry1 INNER JOIN tbl2 ON qry1.HomePhone = tbl2.HomePhone
UNION
SELECT qry1.* FROM qry1 INNER JOIN tbl2 ON qry1.WorkPhone = tbl2.WorkPhone

这应该会给你一个与3个单独查询一样快的结果。它不会那么快,因为UNION会重复消除(当然,个别查询不会消除)。你可以使用UNION ALL,但是如果两个表中有很多行,其中2或3个字段对匹配,那么可能会导致结果中出现大量重复。

答案 1 :(得分:2)

or对于SQL优化器来说可能相当困难。我会建议3个索引和以下查询:

SELECT qry1.*
FROM qry1
WHERE EXISTS (SELECT 1 FROM tbl2 WHERE qry1.CellPhone = tbl2.CellPhone) OR
      EXISTS (SELECT 1 FROM tbl2 WHERE qry1.HomePhone = tbl2.HomePhone) OR
      EXISTS (SELECT 1 FROM tbl2 WHERE qry1.WorkPhone = tbl2.WorkPhone);

三个索引是tbl2(CellPhone)tbl2(HomePhone)tbl2(WorkPhone)

答案 2 :(得分:1)

如果这实际上是一个自我联接,tbl1和qry1中同一个人都存在,那么你可能不会对人们匹配的地方感兴趣,也不会对结果的重复排列感兴趣。我的意思是,自联接通常有两条记录,其中Bob和Jane拥有相同的电话号码,因此您的结果已加入以下记录:

Bob, Jane
Jane, Bob
Jane, Jane
Bob, Bob

其中你可能只需要Bob, Jane,因为它告诉你那两个人有匹配的电话号码。 如果您有一些唯一的ID,那么添加where qry1.SSN < tbl2.SNN将消除许多重复项并减少您的结果集。优选地,该列具有索引。

答案 3 :(得分:0)

以下内容与https://stackoverflow.com/a/27696729/4350148类似,但使用不相交的联合。可能更有效率

 SELECT qry1.* FROM qry1 INNER JOIN tbl2 ON qry1.CellPhone = tbl2.CellPhone
 UNION distinct
 SELECT qry1.* FROM qry1 INNER JOIN tbl2 ON  
    qry1.CellPhone != tbl2.CellPhone 
    and qry1.HomePhone = tbl2.HomePhone
 UNION distinct
 SELECT qry1.* FROM qry1 INNER JOIN tbl2 ON 
    qry1.CellPhone != tbl2.CellPhone 
    and qry1.HomePhone != tbl2.HomePhone
    and qry1.WorkPhone = tbl2.WorkPhone