【问题标题】:What's the difference between "using" and "on" in table joins in MySQL?MySQL中表连接中的“使用”和“打开”有什么区别?
【发布时间】:2010-09-27 01:59:35
【问题描述】:

这是

... T1 join T2 using(ID) where T2.VALUE=42 ...

... T1 join T2 on(T1.ID=T2.ID) where T2.VALUE=42 ...

适用于所有类型的连接?

我对@9​​87654323@ 的理解是它只是on(T1.ID=T2.ID) 的简写。这是真的吗?


现在问另一个问题:

和上面一样吗

... T1 join T2 on(T1.ID=T2.ID and T2.VALUE=42) ...

我认为这不是真的,但为什么呢? on 子句中的条件如何与 join 交互,而 if 它在 where 子句中?

【问题讨论】:

  • 只是出于兴趣,您使用的是什么数据库?我刚刚在 SQL Server 上尝试了 USING 语法,它似乎不起作用。

标签: mysql sql join


【解决方案1】:

我不使用 USING 语法,因为

  1. 我的大多数联接都不适合它(不是正在匹配的同一个字段名,和/或联接中有多个匹配项)和
  2. 在包含两个以上表的情况下,它所转换的内容并不是很明显

假设有 3 个表有 'id' 和 'id_2' 列,是的

T1 JOIN T2 USING(id) JOIN T3 USING(id_2)

成为

T1 JOIN T2 ON(T1.id=T2.id) JOIN T3 ON(T1.id_2=T3.id_2 AND T2.id_2=T3.id_2)

T1 JOIN T2 ON(T1.id=T2.id) JOIN T3 ON(T2.id_2=T3.id_2)

还是别的什么?

为特定的数据库版本找出这个是一个相当简单的练习,但我没有很大的信心相信它在所有数据库中都是一致的,而且我不是唯一需要维护我的代码的人(所以其他人也必须知道它是等价的)。

WHERE 与 ON 的一个明显区别是连接是否在外部:

假设 T1 有一个 ID 字段,一行包含值 1,而 T2 有一个 ID 和 VALUE 字段(一行,ID=1,VALUE=6),那么我们得到:

SELECT T1.ID, T2.ID, T2.VALUE FROM T1 LEFT OUTER JOIN T2 ON(T1.ID=T2.ID) WHERE T2.VALUE=42

不提供任何行,因为需要匹配 WHERE,而

SELECT T1.ID, T2.ID, T2.VALUE FROM T1 LEFT OUTER JOIN T2 ON(T1.ID=T2.ID AND T2.VALUE=42)

将给出一行的值

1, NULL, NULL

因为只有在匹配连接时才需要 ON,因为它是外部的,所以它是可选的。

【讨论】:

    【解决方案2】:

    USING 子句是列的等连接的简写,假设列以相同的名称存在于两个表中:

    A JOIN B USING (column1)
    
    A JOIN B ON A.column1=B.column1
    

    您还可以命名多个列,这使得复合键上的连接非常简单。以下连接应该是等价的:

    A JOIN B USING (column1, column2)
    
    A JOIN B ON A.column1=B.column1 AND A.column2=B.column2
    

    请注意,USING (<columnlist>) 需要有括号,而ON <expr> 不需要有括号(尽管可以在 <expr> 周围使用括号,只是它们可以包含在任何其他上下文中的表达式周围)。

    此外,在查询中连接的其他表可能没有具有该名称的列,否则查询不明确,您应该会收到错误。

    关于您对附加条件的疑问,假设您使用INNER JOIN,它在逻辑上应该给出相同的查询结果,但优化计划可能会受到影响,具体取决于 RDBMS 实现。如果您在连接中包含条件而不是 WHERE 子句,OUTER JOIN 也会给出不同的结果。

    【讨论】:

    • 那么您认为 ON 是该语言的优点还是特性?
    • 当然。当您有任何连接表达式而不是两列相等时,您需要 ON。我更喜欢使用 SQL-92 语法,而不是将连接条件放在 WHERE 子句中。
    【解决方案3】:

    我没有看到其他答案中提到的结果有所不同。如果你这样做:

     JOIN ... ON t1.common = t2.common
    

    那么结果集将有两个名为common 的列,特别是t1.commont2.common,并且尝试引用不合格名称common 将导致查询被拒绝为不明确(即使这两列都必须包含相同的值)。

    另一方面,如果你这样做:

     JOIN ... USING (common)
    

    那么结果集将只有一个名为 common 的列,并且它将是一个非限定名称 - 既不存在 t1.common 也不存在 t2.common

    【讨论】:

      【解决方案4】:

      我相信您是正确的 - USING(xx) 是连接具有相同名称的两列的简写。

      至于第二个问题,两个查询可能相同或可能不同,具体取决于特定于数据库的查询计划器实现。要自己找出答案(至少在 postgres 中),请执行 EXPLAIN SELECT ... 以查看查询计划将如何执行。

      【讨论】:

        【解决方案5】:

        如果只有一个连接,则没有区别。

        using 子句的缺点是两个表必须具有相同的列名。

        【讨论】:

          【解决方案6】:

          您的解释似乎是正确的。 This article 可能会有所帮助。

          至于第二个问题,我不明白为什么您的第三个示例的结果与前两个示例的结果不同。 “ON”子句中的任何条件都与“WHERE”子句中的条件具有相同的含义。

          【讨论】:

          • 否,取决于 ON 子句中的连接类型条件,可能与 where 子句有非常不同的含义。
          • 在示例中,唯一的单词“join”不是“inner join”的同义词吗?
          【解决方案7】:

          你在这里得到了答案,我不需要添加它。一旦我对此进行了性能测试,并且始终使用并且始终比 ON 运行得更快。是的,我说的是 10 到 20 毫秒 :) 我说的是 MySQL

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-05-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-04-17
            • 1970-01-01
            • 2017-08-23
            • 1970-01-01
            相关资源
            最近更新 更多