JOIN的含义就如英文单词“join”一样,连接两张表,大致分为内连接,外连接,右连接,左连接,自然连接。这里描述先甩出一张用烂了的图,然后插入测试数据。

  CREATE TABLE t_blog(
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(50),
typeId INT
);
SELECT * FROM t_blog;
+----+-------+--------+
| id | title | typeId |
+----+-------+--------+
| 1 | aaa | 1 |
| 2 | bbb | 2 |
| 3 | ccc | 3 |
| 4 | ddd | 4 |
| 5 | eee | 4 |
| 6 | fff | 3 |
| 7 | ggg | 2 |
| 8 | hhh | NULL |
| 9 | iii | NULL |
| 10 | jjj | NULL |
+----+-------+--------+
-- 博客的类别
CREATE TABLE t_type(
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20)
);
SELECT * FROM t_type;
+----+------------+
| id | name |
+----+------------+
| 1 | C++ |
| 2 | C |
| 3 | Java |
| 4 | C# |
| 5 | Javascript |
+----+------------+

笛卡尔积:CROSS JOIN

要理解各种JOIN首先要理解笛卡尔积。笛卡尔积就是将A表的每一条记录与B表的每一条记录强行拼在一起。所以,如果A表有n条记录,B表有m条记录,笛卡尔积产生的结果就会产生n*m条记录。下面的例子,t_blog有10条记录,t_type有5条记录,所有他们俩的笛卡尔积有50条记录。有五种产生笛卡尔积的方式如下。

 SELECT * FROM t_blog CROSS JOIN t_type;
SELECT * FROM t_blog INNER JOIN t_type;
SELECT * FROM t_blog,t_type;
SELECT * FROM t_blog NATURE JOIN t_type;
select * from t_blog NATURA join t_type;
+----+-------+--------+----+------------+
| id | title | typeId | id | name |
+----+-------+--------+----+------------+
| 1 | aaa | 1 | 1 | C++ |
| 1 | aaa | 1 | 2 | C |
| 1 | aaa | 1 | 3 | Java |
| 1 | aaa | 1 | 4 | C# |
| 1 | aaa | 1 | 5 | Javascript |
| 2 | bbb | 2 | 1 | C++ |
| 2 | bbb | 2 | 2 | C |
| 2 | bbb | 2 | 3 | Java |
| 2 | bbb | 2 | 4 | C# |
| 2 | bbb | 2 | 5 | Javascript |
| 3 | ccc | 3 | 1 | C++ |
| 3 | ccc | 3 | 2 | C |
| 3 | ccc | 3 | 3 | Java |
| 3 | ccc | 3 | 4 | C# |
| 3 | ccc | 3 | 5 | Javascript |
| 4 | ddd | 4 | 1 | C++ |
| 4 | ddd | 4 | 2 | C |
| 4 | ddd | 4 | 3 | Java |
| 4 | ddd | 4 | 4 | C# |
| 4 | ddd | 4 | 5 | Javascript |
| 5 | eee | 4 | 1 | C++ |
| 5 | eee | 4 | 2 | C |
| 5 | eee | 4 | 3 | Java |
| 5 | eee | 4 | 4 | C# |
| 5 | eee | 4 | 5 | Javascript |
| 6 | fff | 3 | 1 | C++ |
| 6 | fff | 3 | 2 | C |
| 6 | fff | 3 | 3 | Java |
| 6 | fff | 3 | 4 | C# |
| 6 | fff | 3 | 5 | Javascript |
| 7 | ggg | 2 | 1 | C++ |
| 7 | ggg | 2 | 2 | C |
| 7 | ggg | 2 | 3 | Java |
| 7 | ggg | 2 | 4 | C# |
| 7 | ggg | 2 | 5 | Javascript |
| 8 | hhh | NULL | 1 | C++ |
| 8 | hhh | NULL | 2 | C |
| 8 | hhh | NULL | 3 | Java |
| 8 | hhh | NULL | 4 | C# |
| 8 | hhh | NULL | 5 | Javascript |
| 9 | iii | NULL | 1 | C++ |
| 9 | iii | NULL | 2 | C |
| 9 | iii | NULL | 3 | Java |
| 9 | iii | NULL | 4 | C# |
| 9 | iii | NULL | 5 | Javascript |
| 10 | jjj | NULL | 1 | C++ |
| 10 | jjj | NULL | 2 | C |
| 10 | jjj | NULL | 3 | Java |
| 10 | jjj | NULL | 4 | C# |
| 10 | jjj | NULL | 5 | Javascript |
+----+-------+--------+----+------------+

内连接:INNER JOIN

内连接INNER JOIN是最常用的连接操作。从数学的角度讲就是求两个表的交集,从笛卡尔积的角度讲就是从笛卡尔积中挑出ON子句条件成立的记录。有INNER JOIN,WHERE(等值连接),STRAIGHT_JOIN,JOIN(省略INNER)四种写法。至于哪种好我会在MySQL的JOIN(二):优化讲述。示例如下。

SELECT * FROM t_blog INNER JOIN t_type ON t_blog.typeId=t_type.id;
SELECT * FROM t_blog,t_type WHERE t_blog.typeId=t_type.id;
SELECT * FROM t_blog STRAIGHT_JOIN t_type ON t_blog.typeId=t_type.id; --注意STRIGHT_JOIN有个下划线
SELECT * FROM t_blog JOIN t_type ON t_blog.typeId=t_type.id; +----+-------+--------+----+------+
| id | title | typeId | id | name |
+----+-------+--------+----+------+
| 1 | aaa | 1 | 1 | C++ |
| 2 | bbb | 2 | 2 | C |
| 7 | ggg | 2 | 2 | C |
| 3 | ccc | 3 | 3 | Java |
| 6 | fff | 3 | 3 | Java |
| 4 | ddd | 4 | 4 | C# |
| 5 | eee | 4 | 4 | C# |
+----+-------+--------+----+------+

左连接:LEFT JOIN

左连接LEFT JOIN的含义就是求两个表的交集外加左表剩下的数据。依旧从笛卡尔积的角度讲,就是先从笛卡尔积中挑出ON子句条件成立的记录,然后加上左表中剩余的记录(见最后三条)。

SELECT * FROM t_blog LEFT JOIN t_type ON t_blog.typeId=t_type.id;

    +----+-------+--------+------+------+
| id | title | typeId | id | name |
+----+-------+--------+------+------+
| 1 | aaa | 1 | 1 | C++ |
| 2 | bbb | 2 | 2 | C |
| 7 | ggg | 2 | 2 | C |
| 3 | ccc | 3 | 3 | Java |
| 6 | fff | 3 | 3 | Java |
| 4 | ddd | 4 | 4 | C# |
| 5 | eee | 4 | 4 | C# |
| 8 | hhh | NULL | NULL | NULL |
| 9 | iii | NULL | NULL | NULL |
| 10 | jjj | NULL | NULL | NULL |
+----+-------+--------+------+------+

右连接:RIGHT JOIN

同理右连接RIGHT JOIN就是求两个表的交集外加右表剩下的数据。再次从笛卡尔积的角度描述,右连接就是从笛卡尔积中挑出ON子句条件成立的记录,然后加上右表中剩余的记录(见最后一条)。

SELECT * FROM t_blog RIGHT JOIN t_type ON t_blog.typeId=t_type.id;

    +------+-------+--------+----+------------+
| id | title | typeId | id | name |
+------+-------+--------+----+------------+
| 1 | aaa | 1 | 1 | C++ |
| 2 | bbb | 2 | 2 | C |
| 3 | ccc | 3 | 3 | Java |
| 4 | ddd | 4 | 4 | C# |
| 5 | eee | 4 | 4 | C# |
| 6 | fff | 3 | 3 | Java |
| 7 | ggg | 2 | 2 | C |
| NULL | NULL | NULL | 5 | Javascript |
+------+-------+--------+----+------------+

外连接:OUTER JOIN

外连接就是求两个集合的并集。从笛卡尔积的角度讲就是从笛卡尔积中挑出ON子句条件成立的记录,然后加上左表中剩余的记录,最后加上右表中剩余的记录。另外MySQL不支持OUTER JOIN,但是我们可以对左连接和右连接的结果做UNION操作来实现。

SELECT * FROM t_blog LEFT JOIN t_type ON t_blog.typeId=t_type.id
UNION
SELECT * FROM t_blog RIGHT JOIN t_type ON t_blog.typeId=t_type.id; +------+-------+--------+------+------------+
| id | title | typeId | id | name |
+------+-------+--------+------+------------+
| 1 | aaa | 1 | 1 | C++ |
| 2 | bbb | 2 | 2 | C |
| 7 | ggg | 2 | 2 | C |
| 3 | ccc | 3 | 3 | Java |
| 6 | fff | 3 | 3 | Java |
| 4 | ddd | 4 | 4 | C# |
| 5 | eee | 4 | 4 | C# |
| 8 | hhh | NULL | NULL | NULL |
| 9 | iii | NULL | NULL | NULL |
| 10 | jjj | NULL | NULL | NULL |
| NULL | NULL | NULL | 5 | Javascript |
+------+-------+--------+------+------------+

USING子句

MySQL中连接SQL语句中,ON子句的语法格式为:table1.column_name = table2.column_name。当模式设计对联接表的列采用了相同的命名样式时,就可以使用 USING 语法来简化 ON 语法,格式为:USING(column_name)。
所以,USING的功能相当于ON,区别在于USING指定一个属性名用于连接两个表,而ON指定一个条件。另外,SELECT *时,USING会去除USING指定的列,而ON不会。实例如下。

SELECT * FROM t_blog INNER JOIN t_type ON t_blog.typeId =t_type.id;
+----+-------+--------+----+------+
| id | title | typeId | id | name |
+----+-------+--------+----+------+
| 1 | aaa | 1 | 1 | C++ |
| 2 | bbb | 2 | 2 | C |
| 7 | ggg | 2 | 2 | C |
| 3 | ccc | 3 | 3 | Java |
| 6 | fff | 3 | 3 | Java |
| 4 | ddd | 4 | 4 | C# |
| 5 | eee | 4 | 4 | C# |
+----+-------+--------+----+------+ SELECT * FROM t_blog INNER JOIN t_type USING(typeId);
ERROR 1054 (42S22): Unknown column 'typeId' in 'from clause'
SELECT * FROM t_blog INNER JOIN t_type USING(id); -- 应为t_blog的typeId与t_type的id不同名,无法用Using,这里用id代替下。
+----+-------+--------+------------+
| id | title | typeId | name |
+----+-------+--------+------------+
| 1 | aaa | 1 | C++ |
| 2 | bbb | 2 | C |
| 3 | ccc | 3 | Java |
| 4 | ddd | 4 | C# |
| 5 | eee | 4 | Javascript |
+----+-------+--------+------------+

自然连接:NATURE JOIN

自然连接就是USING子句的简化版,它找出两个表中相同的列作为连接条件进行连接。有左自然连接右自然连接普通自然连接之分。在t_blog和t_type示例中,两个表相同的列是id,所以会拿id作为连接条件。
另外千万分清下面三条语句的区别 。
自然连接:SELECT * FROM t_blog NATURAL JOIN t_type;
笛卡尔积:SELECT * FROM t_blog NATURA JOIN t_type;
笛卡尔积:SELECT * FROM t_blog NATURE JOIN t_type;

SELECT * FROM t_blog NATURAL JOIN t_type;
SELECT t_blog.id,title,typeId,t_type.name FROM t_blog,t_type WHERE t_blog.id=t_type.id;
SELECT t_blog.id,title,typeId,t_type.name FROM t_blog INNER JOIN t_type ON t_blog.id=t_type.id;
SELECT t_blog.id,title,typeId,t_type.name FROM t_blog INNER JOIN t_type USING(id); +----+-------+--------+------------+
| id | title | typeId | name |
+----+-------+--------+------------+
| 1 | aaa | 1 | C++ |
| 2 | bbb | 2 | C |
| 3 | ccc | 3 | Java |
| 4 | ddd | 4 | C# |
| 5 | eee | 4 | Javascript |
+----+-------+--------+------------+ SELECT * FROM t_blog NATURAL LEFT JOIN t_type;
SELECT t_blog.id,title,typeId,t_type.name FROM t_blog LEFT JOIN t_type ON t_blog.id=t_type.id;
SELECT t_blog.id,title,typeId,t_type.name FROM t_blog LEFT JOIN t_type USING(id); +----+-------+--------+------------+
| id | title | typeId | name |
+----+-------+--------+------------+
| 1 | aaa | 1 | C++ |
| 2 | bbb | 2 | C |
| 3 | ccc | 3 | Java |
| 4 | ddd | 4 | C# |
| 5 | eee | 4 | Javascript |
| 6 | fff | 3 | NULL |
| 7 | ggg | 2 | NULL |
| 8 | hhh | NULL | NULL |
| 9 | iii | NULL | NULL |
| 10 | jjj | NULL | NULL |
+----+-------+--------+------------+ SELECT * FROM t_blog NATURAL RIGHT JOIN t_type;
SELECT t_blog.id,title,typeId,t_type.name FROM t_blog RIGHT JOIN t_type ON t_blog.id=t_type.id;
SELECT t_blog.id,title,typeId,t_type.name FROM t_blog RIGHT JOIN t_type USING(id); +----+------------+-------+--------+
| id | name | title | typeId |
+----+------------+-------+--------+
| 1 | C++ | aaa | 1 |
| 2 | C | bbb | 2 |
| 3 | Java | ccc | 3 |
| 4 | C# | ddd | 4 |
| 5 | Javascript | eee | 4 |
+----+------------+-------+--------+

补充

博客开头给出的第一张图除去讲了的内连接、左连接、右连接、外连接,还有一些特殊的韦恩图,这里补充一下。

SELECT * FROM t_blog LEFT JOIN t_type ON t_blog.typeId=t_type.id
WHERE t_type.id IS NULL;
+----+-------+--------+------+------+
| id | title | typeId | id | name |
+----+-------+--------+------+------+
| 8 | hhh | NULL | NULL | NULL |
| 9 | iii | NULL | NULL | NULL |
| 10 | jjj | NULL | NULL | NULL |
+----+-------+--------+------+------+
SELECT * FROM t_blog RIGHT JOIN t_type ON t_blog.typeId=t_type.id
WHERE t_blog.id IS NULL;
+------+-------+--------+----+------------+
| id | title | typeId | id | name |
+------+-------+--------+----+------------+
| NULL | NULL | NULL | 5 | Javascript |
+------+-------+--------+----+------------+
SELECT * FROM t_blog LEFT JOIN t_type ON t_blog.typeId=t_type.id
WHERE t_type.id IS NULL
UNION
SELECT * FROM t_blog RIGHT JOIN t_type ON t_blog.typeId=t_type.id
WHERE t_blog.id IS NULL;
+------+-------+--------+------+------------+
| id | title | typeId | id | name |
+------+-------+--------+------+------------+
| 8 | hhh | NULL | NULL | NULL |
| 9 | iii | NULL | NULL | NULL |
| 10 | jjj | NULL | NULL | NULL |
| NULL | NULL | NULL | 5 | Javascript |
+------+-------+--------+------+------------+

好了,大家试一下怎么用吧,希望能帮到是的不是很熟练的童鞋。

MySQL的JOIN用法的更多相关文章

  1. mysql inner join用法

    inner join(等值连接):只返回两个表中联结字段相等的行. left join(左联接):返回包括左表中的所有记录和右表中联结字段相等的记录. right join(右联接):返回包括右表中的 ...

  2. Mysql中Join用法及优化

    Join的几种类型 笛卡尔积(交叉连接) 如果A表有n条记录,B表有m条记录,笛卡尔积产生的结果就会产生n*m条记录.在MySQL中可以为CROSS JOIN或者省略CROSS即JOIN,或者直接用f ...

  3. mysql left join 用法说明

    left join中关于where和on条件的几个知识点: 1.多表left join是会生成一张临时表,并返回给用户 2.where条件是针对最后生成的这张临时表进行过滤,过滤掉不符合where条件 ...

  4. mysql学习之join用法

    转载  一张图看懂 SQL 的各种 join 用法 一.JOIN 使用介绍 下面例子使用的数据表如下: -- ---------------------------- -- Table structu ...

  5. mysql中left join right join inner join用法分析

    mysql数据库中的关联查询,基本都会用到left join,right join,inner join等查询方式,今天来说说这三种用法的区别 1.创建表test1,test2,插入测试数据 #创建表 ...

  6. MySQL基础之STRAIGHT JOIN用法简介

    MySQL基础之STRAIGHT JOIN用法简介 引用mysql官方手册的说法: STRAIGHT_JOIN is similar to JOIN, except that the left tab ...

  7. MySQL应用之CROSS JOIN用法简介教程

    目录 2. cross join用法 @ 本博客翻译自两篇博客的: http://www.mysqltutorial.org/mysql-cross-join/ https://www.w3resou ...

  8. MySQL的JOIN(一):用法

    JOIN的含义就如英文单词"join"一样,连接两张表,大致分为内连接,外连接,右连接,左连接,自然连接.这里描述先甩出一张用烂了的图,然后插入测试数据. CREATE TABLE ...

  9. MySQL中join的用法

    近期用phpcms v9做项目,初期没有问题,后期随着数据量的增大,phpcms v9后台出现的栏目更新不动的情况,初期我以为是程序的问题,进行了程序排查,没有发现任何问题,登录上centos服务器后 ...

随机推荐

  1. windows 64位 安装mvn提示 不是内部或外部命令

    在安装mvn的过程中当在mvn的目录下去执行mvn命令的时候是可以正常执行的,当设置好环境变量后执行后发现提示mvn不是内部命令. 原因是设置的MAVEN_HOME变量未被Path解析,解决办法是 直 ...

  2. Ssh 证书验证登录

    一般使用 PuTTY 等 SSH 客户端来远程管理 Linux 服务器.但是,一般的密码方式登录,容易有密码被暴力破解的问题.所以,一般我们会将 SSH 的端口设置为默认的 22 以外的端口,或者禁用 ...

  3. C++ 类对象的初始化顺序 ZZ

    C++构造函数调用顺序 1.     创建派生类的对象,基类的构造函数优先被调用(也优先于派生类里的成员类): 2.    如果类里面有成员类,成员类的构造函数优先被调用:(也优先于该类本身的构造函数 ...

  4. The package 'MySql.Data' tried to add a framework reference to 'System.Runtime' which was not found in the GAC

    最近在学习Visual Studio连接mysql EF模型.在nuget中安装mysql.data时总是提示The package 'MySql.Data' tried to add a frame ...

  5. CVE-2014-0322漏洞成因与利用分析

    CVE-2014-0322漏洞成因与利用分析 1. 简介 此漏洞是UAF(Use After Free)类漏洞,即引用了已经释放的内存,对指定内存处的值进行了加1.其特点在于攻击者结合flash实现了 ...

  6. 《C++ Primer Plus》读书笔记之——处理数据

    本文旨在记录在阅读<C++ Primer Plus>第五版的过程中,一些重点的知识点,方便以后查阅.本文将不断更新...... 一.第三章 处理数据 1.无符号整型不能存储负数值,其优点是 ...

  7. 原生js实现类名(class)的增、删

    先判断是否有这个类名: function hasClass( elements,cName ){   return !!elements.className.match( new RegExp( &q ...

  8. scanf函数读取缓冲区数据的问题

    标准I\O的缓冲类型 标准I\O根据不同的应用需求,提供了全缓冲.行缓冲.无缓冲三种缓冲方式. 全缓冲:只有当划定的缓冲区被填满或者数据读取至末尾时,才开始执行I\O操作(执行系统提供的read\wr ...

  9. Codeforces Round #535 (Div. 3) E2. Array and Segments (Hard version) 【区间更新 线段树】

    传送门:http://codeforces.com/contest/1108/problem/E2 E2. Array and Segments (Hard version) time limit p ...

  10. Linux学习总结(七)-磁盘管理 du df fdisk

    一 命令df df,即disk free,可用来查看当前系统的挂载情况,也可以用来查看整体磁盘的使用情况df 不带参数,默认以KB单位显示df -i -----查看inodes 使用情况,要清楚理解i ...