Nat*_*ael 243 mysql join using
在MySQL中JOIN,ON和之间有什么区别USING()?据我所知,USING()只是更方便的语法,而ON当列名不相同时允许更多的灵活性.然而,这种差异是如此微小,你会认为他们只是消失了USING().
除此之外还有更多的东西吗?如果是,我应该在特定情况下使用哪个?
Shl*_*ach 378
它主要是语法糖,但有几个不同之处值得注意:
ON是两者中较为普遍的.可以在一列,一组列甚至条件上连接表.例如:
SELECT * FROM world.City JOIN world.Country ON (City.CountryCode = Country.Code) WHERE ...
Run Code Online (Sandbox Code Playgroud)
当两个表共享一个与它们连接的完全相同名称的列时,USING很有用.在这种情况下,可以说:
SELECT ... FROM film JOIN film_actor USING (film_id) WHERE ...
Run Code Online (Sandbox Code Playgroud)
另一个好处是,不需要完全限定连接列:
SELECT film.title, film_id -- film_id is not prefixed
FROM film
JOIN film_actor USING (film_id)
WHERE ...
Run Code Online (Sandbox Code Playgroud)
为了说明,要使用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 ...
Run Code Online (Sandbox Code Playgroud)
请注意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>
Run Code Online (Sandbox Code Playgroud)
Tom*_*Mac 15
当我发现ON比我更有用的时候,我会想到这里USING.这是当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)
;
Run Code Online (Sandbox Code Playgroud)
Vla*_*cea 12
为了演示 USING 和 ON 子句的工作原理,我们假设有以下post数据库表,它们通过表中的外键列引用表中的主键列post_comment形成一对多表关系:post_idpost_commentpost_idpost
父post表有 3 行:
| post_id | title |
|---------|-----------|
| 1 | Java |
| 2 | Hibernate |
| 3 | JPA |
Run Code Online (Sandbox Code Playgroud)
子post_comment表有3条记录:
| post_comment_id | review | post_id |
|-----------------|-----------|---------|
| 1 | Good | 1 |
| 2 | Excellent | 1 |
| 3 | Awesome | 2 |
Run Code Online (Sandbox Code Playgroud)
传统上,在编写INNER JOINorLEFT JOIN查询时,我们碰巧使用 ON 子句来定义连接条件。
例如,要获取评论及其关联的帖子标题和标识符,我们可以使用以下 SQL 投影查询:
SELECT
post.post_id,
title,
review
FROM post
INNER JOIN post_comment ON post.post_id = post_comment.post_id
ORDER BY post.post_id, post_comment_id
Run Code Online (Sandbox Code Playgroud)
并且,我们得到以下结果集:
| post_id | title | review |
|---------|-----------|-----------|
| 1 | Java | Good |
| 1 | Java | Excellent |
| 2 | Hibernate | Awesome |
Run Code Online (Sandbox Code Playgroud)
当外键列和它引用的列具有相同的名称时,我们可以使用 USING 子句,如下例所示:
SELECT
post_id,
title,
review
FROM post
INNER JOIN post_comment USING(post_id)
ORDER BY post_id, post_comment_id
Run Code Online (Sandbox Code Playgroud)
而且,此特定查询的结果集与之前使用 ON 子句的 SQL 查询相同:
| post_id | title | review |
|---------|-----------|-----------|
| 1 | Java | Good |
| 1 | Java | Excellent |
| 2 | Hibernate | Awesome |
Run Code Online (Sandbox Code Playgroud)
USING 子句适用于 Oracle、PostgreSQL、MySQL 和 MariaDB。SQL Server 不支持 USING 子句,因此您需要使用 ON 子句。
USING 子句可与 INNER、LEFT、RIGHT 和 FULL JOIN 语句一起使用。
SELECT *现在,如果我们更改之前的 ON 子句查询以使用以下命令选择所有列SELECT *:
SELECT *
FROM post
INNER JOIN post_comment ON post.post_id = post_comment.post_id
ORDER BY post.post_id, post_comment_id
Run Code Online (Sandbox Code Playgroud)
我们将得到以下结果集:
| post_id | title | post_comment_id | review | post_id |
|---------|-----------|-----------------|-----------|---------|
| 1 | Java | 1 | Good | 1 |
| 1 | Java | 2 | Excellent | 1 |
| 2 | Hibernate | 3 | Awesome | 2 |
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,
post_id是重复的,因为post和post_comment表都包含一post_id列。
SELECT *另一方面,如果我们运行一个SELECT *包含 USING 子句作为 JOIN 条件的查询:
SELECT *
FROM post
INNER JOIN post_comment USING(post_id)
ORDER BY post_id, post_comment_id
Run Code Online (Sandbox Code Playgroud)
我们将得到以下结果集:
| post_id | title | post_comment_id | review |
|---------|-----------|-----------------|-----------|
| 1 | Java | 1 | Good |
| 1 | Java | 2 | Excellent |
| 2 | Hibernate | 3 | Awesome |
Run Code Online (Sandbox Code Playgroud)
您可以看到,这次该列已进行重复数据删除,因此结果集中包含
post_id一列。post_id
如果数据库模式的设计使得外键列名与它们引用的列相匹配,并且 JOIN 条件仅检查外键列值是否等于另一个表中其镜像列的值,那么您可以使用 USING条款。
否则,如果外键列名称与引用列不同或者您想要包含更复杂的联接条件,则应改用 ON 子句。
维基百科有以下信息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中的所有剩余列.
| 归档时间: |
|
| 查看次数: |
158529 次 |
| 最近记录: |