16

这是

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

一样

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

适用于所有类型的连接?

我的理解using(ID)是它只是on(T1.ID=T2.ID). 这是真的?


现在问另一个问题:

以上是不是和上面一样

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

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

4

7 回答 7

18

我不使用 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,因为它是外部的,所以它是可选的。

于 2008-12-16T02:29:42.193 回答
13

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 实现。如果您在联接与子句OUTER JOIN中包含条件,也会给出不同的结果。WHERE

于 2008-12-16T02:41:17.287 回答
5

结果存在差异,我在其他答案中没有提到。如果你这样做:

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

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

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

 JOIN ... USING (common)

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

于 2017-02-02T06:39:34.990 回答
1

你的解释似乎是正确的。这篇文章可能会有所帮助。

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

于 2008-12-16T01:46:52.420 回答
1

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

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

于 2008-12-16T01:47:10.300 回答
1

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

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

于 2008-12-16T01:48:37.143 回答
0

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

于 2012-04-20T17:44:29.257 回答