我想知道在这些联接语句中,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)
这两种写法有性能差异吗?或者算法上的差异?
还是只是语法糖?
我想知道在这些联接语句中,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
=*
, *=
),那么第二种风格将按照预期工作。第一种方式可能不会,而且在SQL Server 2005+中也已经被弃用。我讨厌使用WHERE
强制连接,这看起来很不好,就像一个肮脏的hack。正确的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。 这是我的个人观点。
区别在于可读性和可维护性。 SELECT * FROM a JOIN b ON a.ID = b.ID
可以准确传达您的意图,所有信息都在同一个地方。
我不能确定,因为我没有深入了解最后一个查询优化器,但我非常自信,您看到的差异在性能上是微不足道的,如果有的话。
目前还没有任何人提供关于 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.*
。这是一个与SO问题显式 vs 隐式 SQL 连接重复的问题。一般来说,我认为隐式连接(where 版本)是不好的形式,也不如显式连接(on 版本)清晰。我还认为隐式连接正在被淘汰,但这个不确定。不过两者的执行计划是相同的。
USING
关键字进行等值连接。USING
关键字用于告诉查询批处理在批处理中触发查询时要使用哪个数据库。 - RBT