我想知道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)
是否存在性能差异?还是算法差异?
或者只是语法糖?
答案 0 :(得分:47)
表现没有差异。
然而,第一种款式是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风格也很难得到bollix。如果您错过了一个条件,那么使用旧款式可以轻松获得笛卡尔积(交叉连接)。 ANSI-92会出现语法错误。
编辑:更多澄清
这不仅仅是语法:它是关于语义正确的查询
编辑,2011年12月
SQL Server logical query processing order是FROM,ON,JOIN,WHERE ......
因此,如果混合使用“隐式WHERE内连接”和“显式FROM外连接”,则很可能无法获得预期结果,因为查询不明确...
答案 1 :(得分:4)
不同之处在于可读性和可维护性。 SELECT * FROM a JOIN b ON a.ID = b.ID
在同一个地方传达了你的确切意图。
我不会明确地说,因为我还没有在最后一个查询优化器的引擎盖下,但我非常有信心你会看到一个微不足道的性能差异,如果有的话。
答案 2 :(得分:2)
当你使用WHERE
强制加入时,我很鄙视。它只是让我看起来不对,一个肮脏的黑客。正确的ANSI连接是使用ON:
SELECT
p.Product,
o.Order
FROM
Product p
INNER JOIN
Order o
ON
o.OrderID = p.OrderID
首选加入ON
,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。这是我个人的意见。
答案 3 :(得分:0)
答案 4 :(得分:0)
这是此SO问题的副本:Explicit vs implicit SQL joins。一般来说,我认为隐式(版本)是不好的形式,并不像显式(版本)那样清晰。我也认为隐含的是折旧但不是100%。但两者的执行计划是相同的。
答案 5 :(得分:0)
还没有人提供有关up'
activerecord (6.0.2.1) lib/active_record/migration.rb:1036:in
语法的答案。
这两个查询在逻辑上是等效的,而且从大多数现代优化器的角度来看:
migrate'
activerecord (6.0.2.1) lib/active_record/migration.rb:135:in
这个语义稍有不同:
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
列。尽管PostgreSQL仍然允许对b.id
的限定引用(例如,当需要消除歧义时),但是Oracle则不允许。id
语法的第三个查询中,在Oracle中不再可能投影id
或USING(...)
。