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

发布于 2024-11-01 10:55:31 字数 245 浏览 1 评论 0原文

我想知道 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

独﹏钓一江月 2024-11-08 10:55:31

性能上没有区别。

然而,第一种样式是 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 会出现语法错误。

编辑:更多说明

  • 不使用“连接位置”(隐式)的原因是外部连接的不可靠结果。
  • 如果您使用显式 OUTER JOIN + 隐式 INNER JOIN,您仍然会得到不可靠的结果 + 使用中会出现不一致

这不仅仅是语法:它是关于拥有一个语义上正确的查询

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

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. 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

  • The reason for not using "join the where" (implicit) is the dodgy results with outer joins.
  • If you use explicit OUTER JOINs + implicit INNER JOINs you'll still get dodgy results + you have inconsistency in usage

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...

樱花落人离去 2024-11-08 10:55:31

区别在于可读性和可维护性。 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.

墟烟 2024-11-08 10:55:31

我鄙视你使用 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 的了解还不够。这是我个人的看法。

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:

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. 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 using WHERE as it is much difficult to read.

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. That is my personal opinion.

月下客 2024-11-08 10:55:31

目前还没有人提供有关 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(...) 语法的第三个查询中,不再投影 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:

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. 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. While PostgreSQL still allows for qualifying references to id (e.g. when needing to disambiguate them), Oracle for example doesn't.
  • As a consequence, in the third query with the USING(...) syntax, projecting a.* or b.* is no longer possible in Oracle.
梦行七里 2024-11-08 10:55:31

这是这个问题的重复:显式与隐式 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文