在多个连接中放置条件的位置?

时间:2018-03-07 21:18:21

标签: mysql sql performance join left-join

说我是否有此查询

SELECT TableA.Id, TableA.Number, TableA.Name, TableA.HOl, TableB.Contact, TableC.activity
FROM TableA
left JOIN TableB on TableA.Id = TableB.TableA_Id 
left join TableC on TableB.userid = TableC.userid
where TableA.hol = 50 
order By TableA.Id

除了TableA.Hol在哪里或在ON子句中是否更好?

我不确定它是否有所作为,我试图确定它为什么会变慢。也许这与我的加入有关吗?

3 个答案:

答案 0 :(得分:0)

这是您的查询:

select TableA.Id, TableA.Number, TableA.Name, TableA.HOl, TableB.Contact, TableC.activity
from TableA left join
     TableB
     on TableA.Id = TableB.TableA_Id left join
     TableC
on TableB.userid = TableC.userid
where TableA.hol = 50 
order By TableA.Id;

left join保留第一个表中的所有行,无论on子句的计算结果如何。这意味着第一个表中的条件在on子句中被有效忽略。好吧,并没有完全忽略 - 条件是假的,所以第二个表中的列对于那些行将是NULL

因此,left join中第一个表格的过滤器应该在where子句中。

后续表的条件应该在on子句中。否则,这些条件会将外连接转换为内连接。

答案 1 :(得分:0)

SELECT A.Id, A.Number, A.Name, A.HOl, B.Contact, C.activity
FROM TableA A
LEFT OUTER JOIN TableB B
ON (A.Id = B.TableA_Id)
LEFT OUTER JOIN TableC C
ON (B.userid = C.userid)
AND A.hol = 50
ORDER BY A.Id

如果您引用多个表,则可以使用别名来提高可读性。但这与表现无关。

答案 2 :(得分:0)

无论您使用的是JOIN还是LEFT JOIN,都可以使用ON指定相关信息的关联方式,并使用WHERE进行过滤。

JOIN的情况下,过滤的位置无关紧要;为了便于阅读,您应遵循上述规则。

LEFT JOIN的情况下,结果可能会有所不同。

如果你这样做

EXPLAIN EXTENDED SELECT ...
SHOW WARNINGS;

你可以看到SQL解析器决定做什么。通常,它将ON子句移动到WHERE,表明它们(对于语义)它们所在的位置无关紧要。但是,对于LEFT JOIN,有些内容必须保留在ON

注意另一件事:

FROM a ...
LEFT JOIN b ...
WHERE b.foo = 123

有效地抛弃了LEFTLEFT和非 - LEFT之间的区别在于您是否获得b填充NULLs的行。但是WHERE b.foo = 123说你肯定不想要这样的行。因此,为了清楚读者,请不要说LEFT

所以,我同意你原来的表述。但我也喜欢所有表的短别名。 确保所有列都符合条件 - 读者可能不知道列中的哪个表格。

你的标题是“多个”连接。我讨论了一个JOIN;该讲座适用于任意数量的JOINs