【问题标题】:JOIN-ON vs just = in WHERE clause [closed]JOIN-ON vs just = in WHERE子句[关闭]
【发布时间】:2012-11-09 04:42:49
【问题描述】:

大多数 RDBMS 都支持这两种语法:

SELECT ...
FROM table1 t1 JOIN table2 t2
ON t1.jfield = t2.jfield

还有

SELECT ...
FROM table1 t1, table2 t2
WHERE t1.jfield = t2.jfield

就个人而言,我更喜欢后一个版本,因为它不那么冗长,但它在性能和查询执行方面有什么不同吗?我在这个论坛上看到有人评论说第二种风格已经过时并且表现不佳。

【问题讨论】:

  • 没有问题。你要什么,对两者进行详细分析?基准?要了解 SQL 如何优化您的查询以查看它们是否不同?如果第二种风格实际上已经过时了?
  • 我说“我想知道它在性能上是否有任何差异”
  • 为了您的方便,我把它改成了一个带问号的句子……如果您无法隐含地推断出问题
  • 我更喜欢第一个 (ANSI 92),因为与第二个 (ANSI 89) 不同,它不可能错过连接条件并导致无意的交叉连接。
  • 你在什么样的服务器上工作?如果是 SQL Server 和 SSMS,则在新的查询窗口中键入这两个查询并按 CTRL+L。您可能会看到它们都有相同的查询计划。 SQL 很聪明。但是,在复杂的查询中,使用第二种语法并没有给自己带来任何好处。 SQL 在第一个版本中会更高效。

标签: sql


【解决方案1】:

性能没有区别。但在健壮性方面很多。在第二个例子中去掉 WHERE 子句,你会得到一个不需要的笛卡尔积。在第一个示例中省略 ON,您只会收到语法错误。这对于两个表连接可能很明显,但是一旦您有 10 或 15 个表,这些错误就很难发现。

此外,当您开始使用外连接时,使用 LEFT OUTER JOIN 将适用于所有 DBMS,而任何特定于 DBMS 的外连接语法就是这样:特定于 DBMS(例如 Oracle 的 (+) 运算符不能做任何事情 @987654323 @可以。

所以请习惯使用JOIN 关键字。

【讨论】:

  • 我支持你,但有两点很重要。首先,允许省略 on 子句,至少在 MySQL 中是这样。不符合 ANSI,不愉快,但不是语法错误。其次,Oracle 中的left outer join 可以做什么而(+) 不能做的事情?
  • @Gordon:关于 MySQL:我并不感到惊讶(鉴于 MySQL 的工作方式,它可能只会选择随机行,对吧?) re:Oracle:尝试使用 (+) 进行自外连接,或者尝试对另一个表的子集进行外部连接(对应于... ON l.id = r.id AND r.some_col = 42
【解决方案2】:

查看这两种形式的执行计划,您会发现它们是相同的(对于 MSSQL 肯定如此,但如果不是针对所有数据库,我会吃掉我的帽子)由于执行计划相同,因此会有两种形式之间没有性能差异。

很多人(包括我)试图摆脱第二种形式的原因是:

  • 联接描述 2 个表之间的关系
  • Where 子句定义结果集的过滤器

这 2 种在功能上非常不同,使用第 2 种形式使得阅读和理解查询变得更加困难。

【讨论】:

    【解决方案3】:

    我建议使用第一种语法。它为更新后的代码提供了很好的代码。第二种语法真的很旧,不能更喜欢这个,因为连接所有来自表的结果和过滤数据之后。也许我错了,但我认为如果你有索引和 PK,你可以通过连接获得更高的性能,因为 SQL 服务器可以为这个操作提供更好的支持(例如排序、过滤、子查询等)。 Where 子句用于过滤您的数据最终结果。
    JOINS 是非常强大的工具,因为您可以根据需要仅加入过滤后的数据,而不是加入所有表结果。可能更适合 RAM 或缓存​​。

    第一个 - 您可以添加过滤后的数据,如下所示的语法
    SELECT A., B.
    FROM table_a as A
    INNER JOIN table_B as B ON B.id = A.id -- join table b
    AND B.name = 'bob' AND B.active = 1 -- lets filter more and return only rows for clause


    - 下一个语法显示的子查询,您也可以使用,它只加入过滤的行并只返回该表的特定列
    SELECT a., b., c.flag
    FROM table_a as a
    INNER JOIN table_B as b ON b.id = a.id -- join table b
    AND b.name = 'bob' AND b.active = 1 -- lets filter more and return only rows for clause
    INNER JOIN (
    SELECT id, flag
    FROM table_C
    WHERE active = 1
    ) as c ON c.id = a.id


    它是一种简单、易读且易于维护的代码。

    看看这个链接,代码是不是很漂亮?
    http://www.dpriver.com/products/sqlpp/sqlexamples4.php

    比 WHERE 子句中的 x 条件 ... ofc 你不能在这里使用聚合和子查询 ...我建议了解更多关于连接的信息,你会很高兴程序员 =]
    http://www.w3schools.com/sql/sql_join.asp

    希望有帮助

    【讨论】:

      猜你喜欢
      • 2010-11-04
      • 2011-02-07
      • 2019-01-15
      • 1970-01-01
      • 2019-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-17
      相关资源
      最近更新 更多