我想知道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)
是否存在性能差异?还是算法上的差异?
或者仅仅是语法糖吗?
性能没有差异。
但是,第一种样式是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
如果您有OUTER JOIN(=*
,*=
),则第二种样式将如广告所示那样工作。第一个最可能不会,并且在SQL Server 2005+中也已弃用]
ANSI-92样式也更难以实现。使用较旧的样式,如果您错过条件,则可以轻松获得笛卡尔积(交叉连接)。您将收到ANSI-92的语法错误。
编辑:更多说明
不仅是语法:关于进行语义正确查询
编辑,2011年12月
[SQL Server logical query processing order是FROM,ON,JOIN,WHERE ...
因此,如果您混合使用“隐式WHERE内部联接”和“显式来自外部联接”,则由于查询不明确,您很可能无法获得预期的结果...
不同之处在于可读性和可维护性。 SELECT * FROM a JOIN b ON a.ID = b.ID
在同一地方传达您的确切意图。
由于我还没有获得最后一个查询优化器的支持,所以我不会确切地说,但是我非常有信心,如果有的话,您会发现性能上的微不足道。
当您使用WHERE
强制加入时,我不屑一顾。在我看来,这看起来并不正确,是个肮脏的骇客。正确的ANSI连接是使用ON:
SELECT
p.Product,
o.Order
FROM
Product p
INNER JOIN
Order o
ON
o.OrderID = p.OrderID
加入时首选ON
,并选择WHERE
过滤结果。请记住,WHERE是您要使用的最后一件事,除了根据要过滤结果的位置进行分组和排序。因此,您不应该使用WHERE
来联接表,因为它很难阅读。
SELECT
p.Product,
o.Order
FROM
Product p
INNER JOIN
Order o
ON
o.OrderID = p.OrderID
WHERE
o.Category = 'IT'
最终,您(开发人员)将来可能不在身边,因此可读性和可维护性将帮助那些不得不接管您的代码的灵魂:)。
[当我看到开发人员使用WHERE
来连接他们的表时,通常表明他们对T-SQL的了解不足。那是我的个人看法。
这是此SO问题的重复:Explicit vs implicit SQL joins。通常,我认为隐式(版本)是错误的形式,不如显式(版本上)清晰。我还认为隐式折旧已在贬值,但不是100%。两者的执行计划是相同的。
[尚无人提供有关USING(...)
语法的答案。
虽然这两个查询在逻辑上是等效的,并且从大多数现代优化器的角度来看也是如此:
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 ...
由于各种原因,这是完全不同的,包括:
UNION
或其他设置操作。您可能不知道的,带有星号。a.id
或b.id
列,只有id
列。尽管PostgreSQL仍然允许对id
进行限定引用(例如,当需要消除歧义时),但例如,Oracle不允许。USING(...)
语法的第三个查询中,在Oracle中不再可能投影a.*
或b.*
。