简体   繁体   English

SQL JOIN:USING、ON 或 WHERE 之间有区别吗?

[英]SQL JOIN: is there a difference between USING, ON or WHERE?

I was wondering if there is any difference in the way SQL performs on these join statements:我想知道 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)

Is there a performance difference?有性能差异吗? Or algorithmic difference?还是算法差异?

Or is it just syntactic sugar?或者它只是语法糖?

There is no difference in performance.性能没有区别。

However, the first style is ANSI-89 and will get your legs broken in some shops.然而,第一种款式是 ANSI-89,在一些商店里会弄断你的腿。 Including mine.包括我的。 The second style is ANSI-92 and is much clearer.第二种样式是 ANSI-92 并且更加清晰。

Examples:例子:

Which is the JOIN, which is the filter?哪个是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

If you have OUTER JOINs ( =* , *= ) then the 2nd style will work as advertised.如果您有 OUTER JOINs ( =* , *= ),那么第二种样式将按照宣传的方式工作。 The first most likely won't and is also deprecated in SQL Server 2005+第一个很可能不会,并且在 SQL Server 2005+ 中也不推荐使用

The ANSI-92 style is harder to bollix too. ANSI-92 样式也更难 bollix。 With the older style you can easily end up with a Cartesian product (cross join) if you miss a condition.使用较旧的样式,如果您错过某个条件,您可以轻松地得到笛卡尔积(交叉连接)。 You'll get a syntax error with ANSI-92. ANSI-92 会出现语法错误。

Edit: Some more clarification编辑:更多说明

  • The reason for not using "join the where" (implicit) is the dodgy results with outer joins.不使用“join the where”(隐式)的原因是外部联接的结果不可靠。
  • If you use explicit OUTER JOINs + implicit INNER JOINs you'll still get dodgy results + you have inconsistency in usage如果你使用显式的 OUTER JOINs + 隐式的 INNER JOINs 你仍然会得到狡猾的结果 + 你在使用上不一致

It isn't just syntax : it's about having a semantically correct query这不仅仅是语法:它是关于有一个语义正确的查询

Edit, Dec 2011编辑,2011 年 12 月

SQL Server logical query processing order is FROM, ON, JOIN, WHERE... SQL Server逻辑查询处理顺序为 FROM、ON、JOIN、WHERE...

So if you mix "implicit WHERE inner joins" and "explicit FROM outer joins" you most likely won't get expected results because the query is ambiguous...因此,如果您混合使用“隐式 WHERE 内连接”和“显式 FROM 外连接”,您很可能不会得到预期的结果,因为查询不明确......

The difference is readability and maintainability.区别在于可读性和可维护性。 SELECT * FROM a JOIN b ON a.ID = b.ID conveys your exact intent, all in the same place. SELECT * FROM a JOIN b ON a.ID = b.ID在同一个地方传达您的确切意图。

I won't say definitively since I haven't gotten under the hood of the last query optimizer, but I'm pretty confident you're looking at a trivial difference in performance, if any.我不会明确地说,因为我还没有深入了解最后一个查询优化器,但我非常有信心您正在查看性能上的微小差异(如果有的话)。

I despise when you force a join by using WHERE .我鄙视您使用WHERE强制加入。 It just doesn't to me look right, a dirty hack.它只是在我看来不正确,一个肮脏的黑客。 Proper ANSI join is to use ON:正确的 ANSI 连接是使用 ON:

SELECT 
    p.Product,
    o.Order
FROM 
    Product p
INNER JOIN
    Order o
ON
    o.OrderID = p.OrderID

Prefer using ON when joining and WHERE to filter results.加入时更喜欢使用ONWHERE过滤结果。 Remember WHERE is one of the last things you will use besides grouping and order by where you want to filter your results.记住 WHERE 是除了按要过滤结果的位置进行分组和排序之外,您将使用的最后一件事。 So you shouldn't join your tables using WHERE as it is much difficult to read.所以你不应该使用WHERE加入你的表,因为它很难阅读。

SELECT 
    p.Product,
    o.Order
FROM 
    Product p
INNER JOIN
    Order o
ON
    o.OrderID = p.OrderID
WHERE
    o.Category = 'IT'

In the end you (the developer) might not be around in the future so readability and maintainability will help the pour soul who has to take over your code :).最后,您(开发人员)将来可能不会出现,因此可读性和可维护性将有助于必须接管您的代码的灵魂:)。

When I see developers use WHERE to join their tables it's usually an indication that they don't know enough T-SQL.当我看到开发人员使用WHERE来连接他们的表时,这通常表明他们对 T-SQL 的了解不够。 That is my personal opinion.这是我个人的看法。

No one has provided an answer about the USING(...) syntax yet.还没有人提供有关USING(...)语法的答案。

While these two queries are equivalent logically, and also from the perspective of most modern optimisers:虽然这两个查询在逻辑上是等效的,而且从大多数现代优化器的角度来看:

SELECT * FROM a, b WHERE a.id = b.id
SELECT * FROM a JOIN b ON a.id = b.id

This one has a slightly different semantics:这个语义略有不同:

SELECT * FROM a JOIN b USING (id)

Assuming the following schema:假设以下架构:

CREATE TABLE a (id int, a1 int, a2 int);
CREATE TABLE b (id int, b1 int, b2 int);

The first two queries will have their asterisks expanded to:前两个查询的星号将扩展为:

SELECT a.id, a.a1, a.a2, b.id, b.a1, b.a2 FROM ...

Whereas the third query will have its asterisk expanded to:而第三个查询将其星号扩展为:

SELECT coalesce(a.id, b.id) AS id, a.a1, a.a2, b.a1, b.a2 FROM ...

This is quite different for various reasons, including:由于各种原因,这是完全不同的,包括:

  • The number of projected columns is now 5 instead of 6. This could get in the way when you use UNION or other set operations.投影列的数量现在是 5 而不是 6。这可能会妨碍您使用UNION或其他集合操作。 Which you probably don't, with an asterisk.你可能不知道,带星号。
  • There is no longer a qualified (and duplicate) a.id or b.id column, only an id column.不再有合格(和重复)的a.idb.id列,只有一个id列。 While PostgreSQL still allows for qualifying references to id (eg when needing to disambiguate them), Oracle for example doesn't.虽然 PostgreSQL 仍然允许限定对id引用(例如,当需要消除它们的歧义时),例如 Oracle 则不允许。
  • As a consequence, in the third query with the USING(...) syntax, projecting a.* or b.* is no longer possible in Oracle.因此,在USING(...)语法的第三个查询中,在 Oracle 中不再可能投影a.*b.*

This is a duplicate of this SO question: Explicit vs implicit SQL joins .这是这个 SO 问题的副本: Explicit vsimplicit SQL joins Generally I think the implicit (where version) is bad form and not as clear as the explicit (on version).一般来说,我认为隐式(版本)是不好的形式,不像显式(版本)那样清晰。 I also think the implicit is being depreciated but not 100% on that one.我还认为隐式正在贬值,但不是 100%。 The execution plan is the same for both though.不过,两者的执行计划是相同的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM