SQL JOIN:USING、ON 或 WHERE 之间有区别吗?
我想知道 SQL 在这些 join 语句上执行的方式是否有任何差异:
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?还是算法差异?
或者它只是语法糖?
I was wondering if there is any difference in the way SQL performs on these join statements:
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
性能上没有区别。
然而,第一种样式是 ANSI-89,在某些商店中可能会导致你的腿受伤。包括我的。第二种样式是 ANSI-92,更加清晰。
示例:
哪个是 JOIN,哪个是过滤器?
如果您有 OUTER JOIN(
=*
、*=
),那么第二种样式将按照广告中的方式工作。第一个很可能不会,并且在 SQL Server 2005+ 中也被弃用。 ANSI-92 样式也更难使用。使用旧的样式,如果您错过了某个条件,您很容易得到笛卡尔积(交叉连接)。 ANSI-92 会出现语法错误。
编辑:更多说明
这不仅仅是语法:它是关于拥有一个语义上正确的查询
编辑,2011 年 12 月
SQL Server 逻辑查询处理顺序是FROM、ON、JOIN、WHERE...
因此,如果您混合使用“隐式WHERE内连接”和“显式FROM外连接”,您很可能不会得到预期结果,因为查询不明确......
There is no difference in performance.
However, the first style is ANSI-89 and will get your legs broken in some shops. Including mine. The second style is ANSI-92 and is much clearer.
Examples:
Which is the JOIN, which is the filter?
If you have OUTER JOINs (
=*
,*=
) then the 2nd style will work as advertised. The first most likely won't and is also deprecated in SQL Server 2005+The ANSI-92 style is harder to bollix too. 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.
Edit: Some more clarification
It isn't just syntax: it's about having a semantically correct query
Edit, Dec 2011
SQL Server logical query processing order is 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...
区别在于可读性和可维护性。
SELECT * FROM a JOIN b ON a.ID = b.ID
在同一个位置传达您的确切意图。我不会明确地说,因为我还没有深入了解最后一个查询优化器的原理,但我非常有信心您会看到性能上的微小差异(如果有的话)。
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.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.
我鄙视你使用
WHERE
强制连接。在我看来,这看起来不太对劲,是一个肮脏的黑客行为。正确的 ANSI 连接是使用 ON:连接时优先使用
ON
并使用WHERE
过滤结果。请记住,WHERE 是除了按要过滤结果的位置进行分组和排序之外最后要使用的东西之一。因此,您不应该使用WHERE
连接表,因为它很难阅读。最终,您(开发人员)将来可能不会出现,因此可读性和可维护性将有助于那些必须接管您的代码的灵魂:)。
当我看到开发人员使用
WHERE
来连接他们的表时,这通常表明他们对 T-SQL 的了解还不够。这是我个人的看法。I despise when you force a join by using
WHERE
. It just doesn't to me look right, a dirty hack. Proper ANSI join is to use ON:Prefer using
ON
when joining andWHERE
to filter results. Remember WHERE is one of the last things you will use besides grouping and order by where you want to filter your results. So you shouldn't join your tables usingWHERE
as it is much difficult to read.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. That is my personal opinion.目前还没有人提供有关
USING(...)
语法的答案。虽然这两个查询在逻辑上是等效的,并且从大多数现代优化器的角度来看:
这个查询的语义略有不同:
假设以下模式:
前两个查询将其星号扩展为:
而第三个查询将其星号扩展为:扩展为:
由于各种原因,这完全不同,包括:
UNION
或其他集合操作时,这可能会妨碍。您可能不知道,带有星号。a.id
或b.id
列,只有id
列。虽然 PostgreSQL 仍然允许对id
进行限定引用(例如,当需要消除它们的歧义时),但 Oracle 就不允许这样做。USING(...)
语法的第三个查询中,不再投影a.*
或b.*
在 Oracle 中是可能的。No one has provided an answer about the
USING(...)
syntax yet.While these two queries are equivalent logically, and also from the perspective of most modern optimisers:
This one has a slightly different semantics:
Assuming the following schema:
The first two queries will have their asterisks expanded to:
Whereas the third query will have its asterisk expanded to:
This is quite different for various reasons, including:
UNION
or other set operations. Which you probably don't, with an asterisk.a.id
orb.id
column, only anid
column. While PostgreSQL still allows for qualifying references toid
(e.g. when needing to disambiguate them), Oracle for example doesn't.USING(...)
syntax, projectinga.*
orb.*
is no longer possible in Oracle.请参阅此
INNER JOIN ON 与 WHERE 子句
See this
INNER JOIN ON vs WHERE clause
这是这个问题的重复:显式与隐式 SQL 连接。一般来说,我认为隐式(其中版本)是不好的形式,并且不像显式(在版本上)那么清晰。我还认为隐含的贬值是有的,但不是 100%。不过,两者的执行计划是相同的。
This is a duplicate of this SO question: Explicit vs implicit 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. The execution plan is the same for both though.