SQL JOIN:USING,ON或WHERE有区别吗?

时间:2011-04-13 19:08:56

标签: sql performance syntax join expression

我想知道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)

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

或者只是语法糖?

6 个答案:

答案 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会出现语法错误。

编辑:更多澄清

  • 不使用“join the where”(隐式)的原因是外部联接的狡猾结果。
  • 如果您使用显式OUTER JOIN +隐式INNER JOIN,您仍然会得到狡猾的结果+您的使用不一致

这不仅仅是语法:它是关于语义正确的查询

编辑,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

首选加入ONWHERE过滤结果。请记住,除了分组和排序之外,您将使用的最后一项内容是您希望过滤结果的位置。因此,您不应该使用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);

由于各种原因,这是完全不同的,包括:

  • 现在预计的列数是5,而不是6。这可能会妨碍您使用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中不再可能投影idUSING(...)