MySQL中表连接中的“使用”和“打开”有啥区别?

Posted

技术标签:

【中文标题】MySQL中表连接中的“使用”和“打开”有啥区别?【英文标题】: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 语法,它似乎不起作用。 【参考方案1】:

我不使用 USING 语法,因为

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

假设有 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

【讨论】:

以上是关于MySQL中表连接中的“使用”和“打开”有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

逗号分隔的连接和MySQL中的语法连接有啥区别? [复制]

MySQL Query 中的 HAVING 和 WHERE 有啥区别?

AMQP 中的通道和链接有啥区别?

hive 的元数据存储在 derby 和 mysql 中有啥区别

打开的套接字和连接的套接字有啥区别?

SQL 中的 UNION 和UNION ALL 有啥区别?