我想知道SQL对这些连接语句执行的方式是否有所不同:

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)


是否存在性能差异?还是算法上的差异?

还是语法糖?

评论

我总是尽可能使用“ ON”版本,只是为了明确表明联接条件是什么。在很长的查询中,哪里可能离联接数英里远,让您想知道它的用途。
是否尝试使用explain命令查看查询评估计划?

有人知道它是否在某处被证明没有任何实际差异吗?

SQL INNER JOIN问题的可能重复项

尽管经常被问到,但+1还是引发了良好的讨论。

#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.idb.id列,而只有id列。尽管PostgreSQL仍然允许对id进行合格引用(例如,当需要消除歧义时),但Oracle则不允许。
因此,在使用USING(...)语法的第三个查询中,不再可能投影a.*b.*在Oracle中。