SQL JOIN:使用,打开还是在哪里?

问题描述 投票:43回答:6

我想知道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 performance syntax join expression
6个回答
52
投票

性能没有差异。

但是,第一种样式是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的语法错误。

编辑:更多说明

  • 不使用“ join where where”(隐式)的原因是带有外部联接的模糊结果。
  • 如果您使用显式的OUTER JOINs +隐式的INNER JOINs,您仍然会得到不可靠的结果+使用上的不一致

不仅是语法:关于进行语义正确查询

编辑,2011年12月

[SQL Server logical query processing order是FROM,ON,JOIN,WHERE ...

因此,如果您混合使用“隐式WHERE内部联接”和“显式来自外部联接”,则由于查询不明确,您很可能无法获得预期的结果...


4
投票

不同之处在于可读性和可维护性。 SELECT * FROM a JOIN b ON a.ID = b.ID在同一地方传达您的确切意图。

由于我还没有获得最后一个查询优化器的支持,所以我不会确切地说,但是我非常有信心,如果有的话,您会发现性能上的微不足道。


2
投票

当您使用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的了解不足。那是我的个人看法。



0
投票

这是此SO问题的重复:Explicit vs implicit SQL joins。通常,我认为隐式(版本)是错误的形式,不如显式(版本上)清晰。我还认为隐式折旧已在贬值,但不是100%。两者的执行计划是相同的。


0
投票

[尚无人提供有关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 ...

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

  • 现在预计的列数是5,而不是6。这可能会妨碍您使用UNION或其他设置操作。您可能不知道的,带有星号。
  • 不再有合格的(和重复的)a.idb.id列,只有id列。尽管PostgreSQL仍然允许对id进行限定引用(例如,当需要消除歧义时),但例如,Oracle不允许。
  • 因此,在使用USING(...)语法的第三个查询中,在Oracle中不再可能投影a.*b.*
© www.soinside.com 2019 - 2024. All rights reserved.