SELECT * FROM a,b WHERE a.ID = b.ID
SELECT * FROM a JOIN b ON a.ID = b.ID
SELECT * FROM a JOIN b USING(ID)
是否存在性能差异?还是算法上的差异?
还是语法糖?
#1 楼
性能没什么区别。但是,第一种样式是ANSI-89,在某些商店中会折断你的腿。包括我的。第二种样式是ANSI-92,并且更清晰。
示例:
哪个是JOIN,它是过滤器?
FROM T1,T2,T3....
WHERE T1.ID = T2.ID AND
T1.foo = 'bar' AND T2.fish = 42 AND
T1.ID = T3.ID
FROM T1
INNER JOIN T2 ON T1.ID = T2.ID
INNER JOIN T3 ON T1.ID = T3.ID
WHERE
T1.foo = 'bar' AND T2.fish = 42
如果您有外部联接(
=*
,*=
),则第二种样式将按照广告中的说明工作。第一个最有可能不会,并且在SQL Server 2005+中也不推荐使用。ANSI-92样式也更难以理解。使用较旧的样式,如果您错过条件,则可以轻松获得笛卡尔积(交叉连接)。您会收到ANSI-92的语法错误。
编辑:需要更多说明
不使用“ join the where”(隐式)的原因是带有外部联接的结果模糊。如果您使用显式的OUTER JOINs +隐式的INNER JOINs,您仍然会得到不可靠的结果+您在用法上存在不一致之处
这不只是语法:它是关于语义正确的查询
Edit,2011年12月
SQL Server逻辑查询的处理顺序是FROM,ON,JOIN,WHERE ...
因此,如果您混合使用“隐式WHERE内部联接”和“从外部联接显式”,您很可能不会获得预期的结果,因为查询是不明确的...
评论
您知道它是否只是语法更改而已在某处记录?
– Yochai Timmer
2011年4月13日在19:19
ANSI-92取代ANSI-89?实际上,这与清晰度和可维护性有关。您似乎反对JOIN语法...
– gbn
2011年4月13日在19:22
@Yochai Timmer 92> 89最后我检查了。
– JonH
2011年4月13日在19:27
“哪个是JOIN,哪个是过滤器?” -这些术语是主观的,因此提出了一个问题:如果不查看完整的查询并知道其目的,就无法回答。您可以说对于INNER JOIN来说没有什么区别。如果它们是外部联接(将您暗示的意思)更改为联接条件,则查询结果可能会基于NULL进行更改,但是在不知道设计者意图的情况下,我无法确定这是否“错”。
–有一天
2011年4月14日上午8:55
@ ScottEdwards2000:要点:我不应该尝试使用口语化或鼓励他人这样做!
–有一天
17年11月2日在10:16
#2 楼
区别在于可读性和可维护性。SELECT * FROM a JOIN b ON a.ID = b.ID
可以在同一位置传达您的确切意图。由于我还没有获得上一个查询优化器的支持,所以我不会确切地说,但是我很确定你会观察性能上的微小差异(如果有)。
#3 楼
当您使用WHERE
强制加入时,我不屑一顾。在我看来,这看起来并不正确,是个肮脏的骇客。正确的ANSI连接是使用ON:SELECT
p.Product,
o.Order
FROM
Product p
INNER JOIN
Order o
ON
o.OrderID = p.OrderID
在连接时最好使用
ON
,并使用WHERE
来过滤结果。请记住,WHERE是您要使用的最后一件事,除了根据要过滤结果的位置进行分组和排序。因此,您不应该使用WHERE
来连接表,因为它很难阅读。因此,可读性和可维护性将帮助那些不得不接管您的代码的人:)。当我看到开发人员使用
WHERE
联接其表时,通常表明他们对T-的了解不足SQL。那是我个人的看法。评论
OP并未就不使用ANSI连接语法是否“很漂亮”征求您的意见,只是在实现方面可能存在差异
– jeroenh
2011年4月13日在19:13
@jeroenh-我认为我的帖子明确阐明了他的问题。
– JonH
2011年4月13日在19:14
@jeroenh:这不是很漂亮:它与清晰度,可维护性以及使用将近20年的标准内容有关。 +1。我们不是在这里教和鼓励最佳实践吗?
– gbn
2011年4月13日19:15
我完全同意正确的JOIN语法更具可读性和更好的可维护性,并且在编辑后撤回了我的拒绝投票。但是我保持我的立场:问题是关于可能的性能/算法差异,而不是语法。因此,这仍然无法回答问题。 @oJmHo我们可以进行一场体面的讨论,而不用互相称呼吗?
– jeroenh
2011年4月13日在19:22
@jeroenh-很好,我绝不是说一个比另一个性能更好。这是做事的正确方法,就像早晨起床时为您洗澡的适当方法一样:)。您可以不洗澡而逃脱,但有人会闻到您的气味。就像使用正确的编码约定一样,否则有人会从良好的代码中嗅到不良的代码。
– JonH
2011年4月13日在19:25
#4 楼
参见INNER JOIN ON vs WHERE子句
#5 楼
这是此SO问题的重复:显式与隐式SQL连接。通常,我认为隐式(版本)是错误的形式,不像显式(版本上)那么清晰。我还认为隐式折旧已在贬值,但不是100%。两者的执行计划是相同的。#6 楼
尚无人提供有关USING(...)
语法的答案。 “ lang-sql prettyprint-override”> SELECT * FROM a, b WHERE a.id = b.id
SELECT * FROM a JOIN b ON a.id = b.id
此语义稍有不同:
SELECT * FROM a JOIN b USING (id)
假设以下架构:
CREATE TABLE a (id int, a1 int, a2 int);
CREATE TABLE b (id int, b1 int, b2 int);
前两个查询的星号将扩展为:
SELECT a.id, a.a1, a.a2, b.id, b.a1, b.a2 FROM ...
第三个查询的星号将扩展为:
SELECT coalesce(a.id, b.id) AS id, a.a1, a.a2, b.a1, b.a2 FROM ...
由于各种原因,这是完全不同的,包括:
现在投影的列数为5而不是6。这可能会在您使用
UNION
或其他set操作时出现问题。您可能不带星号。不再有合格的(和重复的)
a.id
或b.id
列,而只有id
列。尽管PostgreSQL仍然允许对id
进行合格引用(例如,当需要消除歧义时),但Oracle则不允许。因此,在使用
USING(...)
语法的第三个查询中,不再可能投影a.*
或b.*
在Oracle中。
评论
我总是尽可能使用“ ON”版本,只是为了明确表明联接条件是什么。在很长的查询中,哪里可能离联接数英里远,让您想知道它的用途。是否尝试使用explain命令查看查询评估计划?
有人知道它是否在某处被证明没有任何实际差异吗?
SQL INNER JOIN问题的可能重复项
尽管经常被问到,但+1还是引发了良好的讨论。