MySQL ON vs USING?

问题描述 投票:223回答:4

在MySQL JOIN中,ONUSING()有什么区别?据我所知,USING()只是更方便的语法,而当列名不相同时,ON允许更多的灵活性。然而,这种差异是如此微小,你认为他们只是取消了USING()

除此之外还有更多的东西吗?如果是,我应该在特定情况下使用哪个?

mysql join using
4个回答
363
投票

它主要是语法糖,但有几个不同之处值得注意:

ON是两者中较为普遍的。可以在一列,一组列甚至条件上连接表。例如:

SELECT * FROM world.City JOIN world.Country ON (City.CountryCode = Country.Code) WHERE ...

当两个表共享一个与它们连接的完全相同名称的列时,USING很有用。在这种情况下,可以说:

SELECT ... FROM film JOIN film_actor USING (film_id) WHERE ...

另一个好处是,不需要完全限定连接列:

SELECT film.title, film_id -- film_id is not prefixed
FROM film
JOIN film_actor USING (film_id)
WHERE ...

为了说明,要使用ON执行上述操作,我们必须写:

SELECT film.title, film.film_id -- film.film_id is required here
FROM film
JOIN film_actor ON (film.film_id = film_actor.film_id)
WHERE ...

请注意film.film_id条款中的SELECT资格。仅仅说film_id是无效的,因为这会造成歧义:

错误1052(23000):字段列表中的列'film_id'不明确

至于select *,连接列在ON的结果集中出现两次,而USING只出现一次:

mysql> create table t(i int);insert t select 1;create table t2 select*from t;
Query OK, 0 rows affected (0.11 sec)

Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

Query OK, 1 row affected (0.19 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> select*from t join t2 on t.i=t2.i;
+------+------+
| i    | i    |
+------+------+
|    1 |    1 |
+------+------+
1 row in set (0.00 sec)

mysql> select*from t join t2 using(i);
+------+
| i    |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

mysql>

15
投票

当我发现ONUSING更有用时,我想我会在这里筹码。这是当OUTER加入被引入查询时。

ON受益于允许在保持OUTER连接的同时限制查询是OUTER加入的表的结果集。试图通过指定WHERE子句来限制结果集,实际上会将OUTER连接更改为INNER连接。

当然这可能是一个相对的角落案例。值得把它放在那里.....

例如:

CREATE TABLE country (
   countryId int(10) unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
   country varchar(50) not null,
  UNIQUE KEY countryUIdx1 (country)
) ENGINE=InnoDB;

insert into country(country) values ("France");
insert into country(country) values ("China");
insert into country(country) values ("USA");
insert into country(country) values ("Italy");
insert into country(country) values ("UK");
insert into country(country) values ("Monaco");


CREATE TABLE city (
  cityId int(10) unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
  countryId int(10) unsigned not null,
  city varchar(50) not null,
  hasAirport boolean not null default true,
  UNIQUE KEY cityUIdx1 (countryId,city),
  CONSTRAINT city_country_fk1 FOREIGN KEY (countryId) REFERENCES country (countryId)
) ENGINE=InnoDB;


insert into city (countryId,city,hasAirport) values (1,"Paris",true);
insert into city (countryId,city,hasAirport) values (2,"Bejing",true);
insert into city (countryId,city,hasAirport) values (3,"New York",true);
insert into city (countryId,city,hasAirport) values (4,"Napoli",true);
insert into city (countryId,city,hasAirport) values (5,"Manchester",true);
insert into city (countryId,city,hasAirport) values (5,"Birmingham",false);
insert into city (countryId,city,hasAirport) values (3,"Cincinatti",false);
insert into city (countryId,city,hasAirport) values (6,"Monaco",false);

-- Gah. Left outer join is now effectively an inner join 
-- because of the where predicate
select *
from country left join city using (countryId)
where hasAirport
; 

-- Hooray! I can see Monaco again thanks to 
-- moving my predicate into the ON
select *
from country co left join city ci on (co.countryId=ci.countryId and ci.hasAirport)
; 

9
投票

Wikipedia有关于USING的以下信息:

然而,USING结构不仅仅是语法糖,因为结果集与具有显式谓词的版本的结果集不同。具体来说,USING列表中提到的任何列只会出现一次,具有非限定名称,而不是连接中的每个表一次。在上面的例子中,将有一个DepartmentID列,没有employee.DepartmentID或department.DepartmentID。

它正在谈论的表:

Postgres文档也很好地定义了它们:

ON子句是最常见的连接条件:它采用与WHERE子句中使用的布尔值表达式相同的布尔值表达式。如果ON表达式的计算结果为true,则T1和T2中的一对行匹配。

USING子句是一种速记,允许您利用连接的双方对连接列使用相同名称的特定情况。它采用逗号分隔的共享列名列表,并形成一个连接条件,包括每个列的相等比较。例如,用USING(a,b)连接T1和T2产生连接条件ON T1.a = T2.a AND T1.b = T2.b.

此外,JOIN USING的输出会抑制冗余列:不需要打印两个匹配的列,因为它们必须具有相等的值。当JOIN ON生成T1中的所有列,后跟T2中的所有列时,JOIN USING为每个列出的列对(按列出的顺序)生成一个输出列,然后是T1中的任何剩余列,后跟T2中的所有剩余列。


0
投票

对于那些在phpMyAdmin中进行实验的人来说,只需一句话:

phpMyAdmin似乎与USING有一些问题。为了记录,这是在Linux Mint上运行的phpMyAdmin,版本:“4.5.4.1deb2ubuntu2”,数据库服务器:“10.2.14-MariaDB-10.2.14 + maria~xenial - mariadb.org二进制分发”。

我在phpMyAdmin和终端(命令行)中使用SELECTJOIN运行USING命令,而phpMyAdmin中的命令会产生一些令人困惑的响应:

1)最后的LIMIT条款似乎被忽略了。 2)页面顶部报告的假定行数,结果有时是错误的:例如返回4,但在顶部显示“显示行0 - 24(总共2503,查询耗时0.0018秒。) “

正常登录到mysql并运行相同的查询不会产生这些错误。使用JOIN ... ON ...在phpMyAdmin中运行相同的查询时也不会发生这些错误。大概是一个phpMyAdmin错误。

© www.soinside.com 2019 - 2024. All rights reserved.