MySQL的Join使用
在MySQL(以5.1为例)中,表连接的语法可以参见MySQL官方手册:MySQL官方手册-JOIN
在查询中,连接的语法类似
- SELECT select_expr FROM table_references
table_references(对表的引用)的定义如下(也可以看成连接表达式):(晕晕晕哈)
- table_references:
- table_reference [, table_reference] ...
- table_reference:
- table_factor
- | join_table
- table_factor:
- tbl_name [[AS] alias] [index_hint_list]
- | table_subquery [AS] alias
- | ( table_references )
- | { OJ table_reference LEFT OUTER JOIN table_reference
- ON conditional_expr }
- join_table:
- table_reference [INNER | CROSS] JOIN table_factor [join_condition]
- | table_reference STRAIGHT_JOIN table_factor
- | table_reference STRAIGHT_JOIN table_factor ON conditional_expr
- | table_reference {LEFT|RIGHT} [OUTER] JOIN table_reference join_condition
- | table_reference NATURAL [{LEFT|RIGHT} [OUTER]] JOIN table_factor
- join_condition:
- ON conditional_expr
- | USING (column_list)
- index_hint_list:
- index_hint [, index_hint] ...
- index_hint:
- USE {INDEX|KEY}
- [{FOR {JOIN|ORDER BY|GROUP BY}] ([index_list])
- | IGNORE {INDEX|KEY}
- [{FOR {JOIN|ORDER BY|GROUP BY}] (index_list)
- | FORCE {INDEX|KEY}
- [{FOR {JOIN|ORDER BY|GROUP BY}] (index_list)
- index_list:
- index_name [, index_name] ...
其中,table_factor是基本的表选择,而join_table是基于表的一些扩展。
下面,通过实验介绍一下表连接。
首先,假设有以下几个表
| book | |
|---|---|
| 1 | java |
| 2 | c++ |
| 3 | php |
| author | |
|---|---|
| 2 | zhang |
| 3 | wang |
| 4 | li |
| year | |
|---|---|
| zhang | 2003 |
| ma | 2006 |
| liu | 2011 |
Inner Join 内连接
将两个表中存在连接关系的字段,组成的记录集,叫做内连接。
内连接等价于
- mysql> select table1.id as id,book,author from table1, table2 where table1.id=table2.id;
- +------+------+--------+
- | id | book | author |
- +------+------+--------+
- | 2 | c++ | zhang |
- | 3 | php | wang |
- +------+------+--------+
- 2 rows in set (0.00 sec)
- mysql> select * from table1 inner join table2 using (id);
- +------+------+--------+
- | id | book | author |
- +------+------+--------+
- | 2 | c++ | zhang |
- | 3 | php | wang |
- +------+------+--------+
- 2 rows in set (0.00 sec)
可以看出,两者是等价的。没有Using子句的Inner Join相当于是求两个table的笛卡尔积。
Cross Join 交叉连接
在Mysql中,Cross Join可以用逗号表达式表示,例如(table1, table 2)。在Mysql中,Cross Join 和
Inner Join 是等价的,但是在标准SQL中,它们并不等价,Inner Join 用于带有on表达式的连接,反之用Cross
Join。以下两个SQL语句是等价的。
Cross Join 指的是两个table的笛卡尔积。以下三句SQL是等价的。
- mysql> select * from table1 inner join table2;
- mysql> select * from table1 cross join table2;
- mysql> select * from (table1, table2);
- mysql> select * from table1 nature join table2;
- 结果集:
- +------+------+------+--------+
- | id | book | id | author |
- +------+------+------+--------+
- | 1 | java | 2 | zhang |
- | 2 | c++ | 2 | zhang |
- | 3 | php | 2 | zhang |
- | 1 | java | 3 | wang |
- | 2 | c++ | 3 | wang |
- | 3 | php | 3 | wang |
- | 1 | java | 4 | li |
- | 2 | c++ | 4 | li |
- | 3 | php | 4 | li |
- +------+------+------+--------+
不难理解,下面两句SQL也是等价的。
- mysql> select * from table1 left join (table2, table3) on (table2.id = table1.id and table2.author = table3.author);
- mysql> select * from table1 left join (table2 cross join table3) on (table2.id = table1.id and table2.author = table3.author);
- 结果集:
- +------+------+------+--------+--------+------+
- | id | book | id | author | author | year |
- +------+------+------+--------+--------+------+
- | 1 | java | NULL | NULL | NULL | NULL |
- | 2 | c++ | 2 | zhang | zhang | 2003 |
- | 3 | php | NULL | NULL | NULL | NULL |
- +------+------+------+--------+--------+------+
Natural Join 自然连接
NATURAL [LEFT] JOIN:这个句子的作用相当于INNER JOIN,或者是在USING子句中包含了联结的表中所有公共字段的Left JOIN(左联结)。
也就是说:下面两个SQL是等价的。
- mysql> select * from table1 natural join table2;
- mysql> select * from table1 inner join table2 using (id);
- 结果集:
- +------+------+--------+
- | id | book | author |
- +------+------+--------+
- | 2 | c++ | zhang |
- | 3 | php | wang |
- +------+------+--------+
同时,下面两个SQL也是等价的。
- mysql> select * from table1 natural left join table2;
- mysql> select * from table1 left join table2 using(id);
- 结果集:
- +------+------+--------+
- | id | book | author |
- +------+------+--------+
- | 1 | java | NULL |
- | 2 | c++ | zhang |
- | 3 | php | wang |
- +------+------+--------+
Left Join 左外连接
左外连接A、B表的意思就是将表A中的全部记录和表B中字段连接形成的记录集,这里注意的是最后出来的记录集会包括表A的全部记录。
左连接表1,表二等价于右连接表二,表一。如下两个SQL是等价的:
- mysql> select * from table1 left join table2 using (id);
- mysql> select * from table2 right join table1 using (id);
- 结果集:
- +------+------+--------+
- | id | book | author |
- +------+------+--------+
- | 1 | java | NULL |
- | 2 | c++ | zhang |
- | 3 | php | wang |
- +------+------+--------+
Right Join 右外连接
右外连接和左外连接是类似的。为了方便数据库便于访问,推荐使用左外连接代替右外连接。
最后,讲一下Mysql表连接的一些注意事项。
1、两个表求差集的方法
如果求 左表 - 右表 的差集,使用类似下面的SQL:
- SELECT left_tbl.* FROM left_tbl LEFT JOIN right_tbl ON left_tbl.id = right_tbl.id WHERE right_tbl.id IS NULL;
- 例如
- mysql> select table1.* from table1 left join table2 using(id) where table2.id is null;
- +------+------+
- | id | book |
- +------+------+
- | 1 | java |
- +------+------+
- 1 row in set (0.00 sec)
2、Using子句
Using子句可以使用On子句重写。但是使用Select * 查询出的结果有差别。以下两句话是等价的:
- mysql> select id, book, author from table1 join table2 using (id);
- mysql> select table1.id, book, author from table1 join table2 on table1.id=table2.id;
- 结果集:
- +------+------+--------+
- | id | book | author |
- +------+------+--------+
- | 2 | c++ | zhang |
- | 3 | php | wang |
- +------+------+--------+
但是下面两个有些许不同,使用on时候,重复的部分会被输出两次。
- mysql> select * from table1 join table2 using (id);
- +------+------+--------+
- | id | book | author |
- +------+------+--------+
- | 2 | c++ | zhang |
- | 3 | php | wang |
- +------+------+--------+
- 2 rows in set (0.00 sec)
- mysql> select * from table1 join table2 on table1.id=table2.id;
- +------+------+------+--------+
- | id | book | id | author |
- +------+------+------+--------+
- | 2 | c++ | 2 | zhang |
- | 3 | php | 3 | wang |
- +------+------+------+--------+
- 2 rows in set (0.00 sec)
3、Straight Join的使用
STRAIGHT_JOIN 和 JOIN相似,除了大部分情况下,在使用STRAIGHT_JOIN时候,先读右表后读左表。而在大部分情况下是先读左表的。STRAIGHT_JOIN仅用于少数情况下的表连接性能优化,比如右表记录数目明显少于左表。
4、Mysql表连接的运算顺序
在MySQL 5.1版本中,INNER JOIN, CROSS JOIN, LEFT JOIN, 和RIGHT JOIN 比逗号表达式具有更高的优先级。
因此SQL1被解析成SQL3,而不是SQL2。
- SQL1 : SELECT * FROM t1, t2 JOIN t3 ON (t1.i1 = t3.i3);
- SQL2 : SELECT * FROM (t1, t2) JOIN t3 ON (t1.i1 = t3.i3);
- SQL3 : SELECT * FROM t1, (t2 JOIN t3 ON (t1.i1 = t3.i3));
因此会报错,找不到i1列。因此以后在写这样的查询的时候,最好写明白,不要省略括号,这样能避免很多错误。
5、循环的自然连接
在MySQL 5.1版本中,SQL1等价于SQL3, 而在MySQL以前版本中,SQL1等价于SQL2。
- SQL1 : SELECT ... FROM t1 NATURAL JOIN t2 NATURAL JOIN t3;
- SQL2 : SELECT ... FROM t1, t2, t3 WHERE t1.b = t2.b AND t2.c = t3.c;
- SQL3 : SELECT ... FROM t1, t2, t3 WHERE t1.b = t2.b AND t2.c = t3.c AND t1.a = t3.a;
MySQL的Join使用的更多相关文章
- MySQL Left Join,Right Join
魂屁,东西发这里了关于Left Join,Right Join的 在讲MySQL的Join语法前还是先回顾一下联结的语法,呵呵,其实连我自己都忘得差不多了,那就大家一起温习吧(如果内容有错误或有疑问, ...
- MySQL Full Join的实现
MySQL Full Join的实现 由于MySQL不支持FULL JOIN,以下是替代方法 left join + union(可去除反复数据)+ right join select * from ...
- mysql left join
MySQL左连接不同于简单连接.MySQL LEFT JOIN提供该表额外字段在左侧. 如果使用LEFT JOIN,得到的所有记录的匹配方式相同, 在左边表中得到的每个记录不匹配也会有一个额外的记录. ...
- MySQL的JOIN(一):用法
JOIN的含义就如英文单词"join"一样,连接两张表,大致分为内连接,外连接,右连接,左连接,自然连接.这里描述先甩出一张用烂了的图,然后插入测试数据. CREATE TABLE ...
- MySQL的JOIN(三):JOIN优化实践之内循环的次数
这篇博文讲述如何优化内循环的次数.内循环的次数受驱动表的记录数所影响,驱动表记录数越多,内循环就越多,连接效率就越低下,所以尽量用小表驱动大表.先插入测试数据. CREATE TABLE t1 ( i ...
- MySQL的JOIN(四):JOIN优化实践之快速匹配
这篇博文讲述如何优化扫描速度.我们通过MySQL的JOIN(二):JOIN原理得知了两张表的JOIN操作就是不断从驱动表中取出记录,然后查找出被驱动表中与之匹配的记录并连接.这个过程的实质就是查询操作 ...
- MySQL的JOIN(五):JOIN优化实践之排序
这篇博文讲述如何优化JOIN查询带有排序的情况.大致分为对连接属性排序和对非连接属性排序两种情况.插入测试数据. CREATE TABLE t1 ( id INT PRIMARY KEY AUTO_I ...
- Mysql Nested-Loop Join Algorithms
MySQL在多表之间执行join时,利用一种nested-loop algorithm 或者其变种:(嵌套循环) Nested-Loop Join Algorithm 一个简单的嵌套循环连 ...
- [转]MySQL update join语句
原文地址:https://www.jianshu.com/p/f99665266bb1 在本教程中,您将学习如何使用MySQL UPDATE JOIN语句来执行跨表更新.我们将逐步介绍如何使用INNE ...
- mysql的join操作
一.Join语法概述 join 用于多表中字段之间的联系,语法如下: ... FROM table1 INNER|LEFT|RIGHT JOIN table2 ON conditiona table1 ...
随机推荐
- CAS 服务端数据库认证
CAS-服务端数据库认证 数据认证需要相关的jar包: cas-server-support-jdbc-x.x.x.jar MySQL-connector-Java-x.x.x-bin.jar 修改C ...
- 玩转X-CTR100 l STM32F4 l 电机正交编码器
我造轮子,你造车,创客一起造起来!塔克创新资讯[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ] 本文介绍X-CTR100控制器的电机正交编码器,X- ...
- js创建表单并提交
1.脚本 Util = { post : function(URL, PARAMS){ //虚拟表单实现post提交 var temp = document.createElement("f ...
- firefox下reset()不好使的问题
最近在测试项目时发现,在firefox下,form.reset()方法对于隐藏的<input>等不起效果,导致程序中出现了错误,以下面为例: js代码: document.agentFor ...
- UIViewController之间的相互跳转
一.最普通的视图控制器UIViewContoller 一个普通的视图控制器一般只有模态跳转的功能(ipad我不了解除外,这里只说iPhone),这个方法是所有视图控制器对象都可以用的,而实现这种功能, ...
- Python: PS 图像调整--明度调整
本文用 Python 实现 PS 图像调整中的明度调整: 我们知道,一般的非线性RGB亮度调整只是在原有R.G.B值基础上增加和减少一定量来实现的,而PS的明度调整原理还得从前面那个公式上去找.我们将 ...
- C# 跨线程更新UI界面的适当的处理方式,友好的退出界面的机制探索
本文主要讲讲C#窗体的程序中一个经常遇到的情况,就是在退出窗体的时候的,发生了退出的异常. 工业软件技术交流群:群1:592132877(满) 群2:948305931 欢迎技术探讨 我们先 ...
- Grunt新手入门篇
今天看到一篇通俗易懂的Grunt入门文章,博主写得很用心,原文请戳:http://yujiangshui.com/grunt-basic-tutorial/ 当时学习 Grunt 的时候,真是很头疼. ...
- HDU 4185
http://acm.hdu.edu.cn/showproblem.php?pid=4185 两个挨着的'#'可以配成一对,求最多能配成几对 挨着的'#'就连边,然后求一次最大匹配,答案是最大匹配除以 ...
- mkbootimg hacking
/********************************************************************** * mkbootimg hacking * 声明: * ...