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 ...
适用于所有类型的连接?
我对@987654323@ 的理解是它只是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.common
和t2.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 Query 中的 HAVING 和 WHERE 有啥区别?