更多情况下,我们查询的数据来源于多张表,所有有必要了解一下MySQL中的连接查询。

SQL中将连接查询分成四类:交叉连接,内连接,外连接和自然连接。

数据准备

student表

-- ----------------------------
-- Table structure for `student`
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(10) DEFAULT NULL,
`age` tinyint(4) DEFAULT NULL,
`classId` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8; -- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES ('1', 's1', '20', '1');
INSERT INTO `student` VALUES ('2', 's2', '22', '1');
INSERT INTO `student` VALUES ('3', 's3', '22', '2');
INSERT INTO `student` VALUES ('4', 's4', '22', null);

class表

-- ----------------------------
-- Table structure for `class`
-- ----------------------------
DROP TABLE IF EXISTS `class`;
CREATE TABLE `class` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`cname` varchar(10) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; -- ----------------------------
-- Records of class
-- ----------------------------
INSERT INTO `class` VALUES ('1', '一班');
INSERT INTO `class` VALUES ('2', '二班');
INSERT INTO `class` VALUES ('3', '');

score表

-- ----------------------------
-- Table structure for `score`
-- ----------------------------
DROP TABLE IF EXISTS `score`;
CREATE TABLE `score` (
`id` int(11) DEFAULT NULL,
`name` varchar(10) DEFAULT NULL,
`score` decimal(4,1) DEFAULT NULL,
`studentId` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ----------------------------
-- Records of score
-- ----------------------------
INSERT INTO `score` VALUES ('1', '语文', '90.0', '1');
INSERT INTO `score` VALUES ('2', '数学', '95.0', '1');
INSERT INTO `score` VALUES ('3', '语文', '92.0', '2');
INSERT INTO `score` VALUES ('4', '数学', '88.0', '2');
INSERT INTO `score` VALUES ('5', '语文', '96.0', '3');
INSERT INTO `score` VALUES ('6', '数学', null, '3');

交叉连接

交叉连接(CROSS JOIN)是用左表中的每一行与右表中的每一行进行连接,不能使用ON关键字。所得到的结果将是这两个表中各行数据的所有组合,即这两个表所有数据的笛卡尔积。如果A表有4条记录,B表有3条,则结果有4*3=12条记录。

mysql> SELECT * FROM student CROSS JOIN class;
+----+------+-----+---------+----+-------+
| id | name | age | classId | id | cname |
+----+------+-----+---------+----+-------+
| 1 | s1 | 20 | 1 | 1 | 一班 |
| 1 | s1 | 20 | 1 | 2 | 二班 |
| 1 | s1 | 20 | 1 | 3 | |
| 2 | s2 | 22 | 1 | 1 | 一班 |
| 2 | s2 | 22 | 1 | 2 | 二班 |
| 2 | s2 | 22 | 1 | 3 | |
| 3 | s3 | 22 | 2 | 1 | 一班 |
| 3 | s3 | 22 | 2 | 2 | 二班 |
| 3 | s3 | 22 | 2 | 3 | |
| 4 | s4 | 22 | NULL | 1 | 一班 |
| 4 | s4 | 22 | NULL | 2 | 二班 |
| 4 | s4 | 22 | NULL | 3 | |
+----+------+-----+---------+----+-------+
12 rows in set

如果给交叉连接加上WHERE关键字,此时将返回符合条件的结果集,这时候与内连接的执行结果一样。

mysql> SELECT * FROM student CROSS JOIN class WHERE student.classId = class.id;
+----+------+-----+---------+----+-------+
| id | name | age | classId | id | cname |
+----+------+-----+---------+----+-------+
| 1 | s1 | 20 | 1 | 1 | 一班 |
| 2 | s2 | 22 | 1 | 1 | 一班 |
| 3 | s3 | 22 | 2 | 2 | 二班 |
+----+------+-----+---------+----+-------+
3 rows in set

内连接

内连接(INNER JOIN)是用左表中的每一行与右表中的所有记录进行匹配,查询的结果为两个表经过ON条件过滤后的笛卡尔积

mysql> SELECT * FROM student INNER JOIN class ON student.classId = class.id; -- 推荐写法,INNER可写可不写
+----+------+-----+---------+----+-------+
| id | name | age | classId | id | cname |
+----+------+-----+---------+----+-------+
| 1 | s1 | 20 | 1 | 1 | 一班 |
| 2 | s2 | 22 | 1 | 1 | 一班 |
| 3 | s3 | 22 | 2 | 2 | 二班 |
+----+------+-----+---------+----+-------+
3 rows in set

等价于

mysql> SELECT * FROM student, class WHERE student.classId = class.id;
+----+------+-----+---------+----+------+
| id | name | age | classId | id | name |
+----+------+-----+---------+----+------+
| 1 | s1 | 20 | 1 | 1 | 一班 |
| 2 | s2 | 22 | 1 | 1 | 一班 |
| 3 | s3 | 22 | 2 | 2 | 二班 |
+----+------+-----+---------+----+------+
3 rows in set

可以连接多张表

mysql> SELECT * FROM student
-> JOIN class ON student.classId = class.id
-> JOIN score ON student.id = score.studentId;
+----+------+-----+---------+----+-------+----+------+-------+-----------+
| id | name | age | classId | id | cname | id | name | score | studentId |
+----+------+-----+---------+----+-------+----+------+-------+-----------+
| 1 | s1 | 20 | 1 | 1 | 一班 | 1 | 语文 | 90 | 1 |
| 1 | s1 | 20 | 1 | 1 | 一班 | 2 | 数学 | 95 | 1 |
| 2 | s2 | 22 | 1 | 1 | 一班 | 3 | 语文 | 92 | 2 |
| 2 | s2 | 22 | 1 | 1 | 一班 | 4 | 数学 | 88 | 2 |
| 3 | s3 | 22 | 2 | 2 | 二班 | 5 | 语文 | 96 | 3 |
| 3 | s3 | 22 | 2 | 2 | 二班 | 6 | 数学 | NULL | 3 |
+----+------+-----+---------+----+-------+----+------+-------+-----------+
6 rows in set

外连接

左外连接

左外连接包含LEFT JOIN左表所有行,如果左表中某行在右表没有匹配,则结果中对应行右表的部分全部为空(NULL)。

mysql> SELECT * FROM student LEFT JOIN class ON student.classId = class.id; -- 或者LEFT OUTER JOIN
+----+------+-----+---------+------+-------+
| id | name | age | classId | id | cname |
+----+------+-----+---------+------+-------+
| 1 | s1 | 20 | 1 | 1 | 一班 |
| 2 | s2 | 22 | 1 | 1 | 一班 |
| 3 | s3 | 22 | 2 | 2 | 二班 |
| 4 | s4 | 22 | NULL | NULL | NULL |
+----+------+-----+---------+------+-------+
4 rows in set

右外连接

右外连接包含RIGHT JOIN左表所有行,如果右表中某行在左表没有匹配,则结果中对应行左表的部分全部为空(NULL)。

mysql> SELECT * FROM student RIGHT JOIN class ON student.classId = class.id; -- 或者RIGHT OUTER JOIN
+------+------+------+---------+----+-------+
| id | name | age | classId | id | cname |
+------+------+------+---------+----+-------+
| 1 | s1 | 20 | 1 | 1 | 一班 |
| 2 | s2 | 22 | 1 | 1 | 一班 |
| 3 | s3 | 22 | 2 | 2 | 二班 |
| NULL | NULL | NULL | NULL | 3 | |
+------+------+------+---------+----+-------+
4 rows in set

全外连接

如果左表中某行在右表没有匹配,则结果中对应行右表的部分全部为空(NULL),如果右表中某行在左表没有匹配,则结果中对应行左表的部分全部为空(NULL)。MySQL不支持FULL JOIN,但是我们可以对左连接和右连接的结果做UNION操作来实现

mysql> SELECT * FROM student LEFT JOIN class ON student.classId = class.id
-> UNION
-> SELECT * FROM student RIGHT JOIN class ON student.classId = class.id;
+------+------+------+---------+------+-------+
| id | name | age | classId | id | cname |
+------+------+------+---------+------+-------+
| 1 | s1 | 20 | 1 | 1 | 一班 |
| 2 | s2 | 22 | 1 | 1 | 一班 |
| 3 | s3 | 22 | 2 | 2 | 二班 |
| 4 | s4 | 22 | NULL | NULL | NULL |
| NULL | NULL | NULL | NULL | 3 | |
+------+------+------+---------+------+-------+
5 rows in set

自然连接

自然连接无需指定连接列,SQL会检查两个表中是否有相同名称的列,且相同的列名称只能有一个,自然连接基本不用。

mysql> SELECT * FROM student NATURAL JOIN class;
+----+------+-----+---------+-------+
| id | name | age | classId | cname |
+----+------+-----+---------+-------+
| 1 | s1 | 20 | 1 | 一班 |
| 2 | s2 | 22 | 1 | 二班 |
| 3 | s3 | 22 | 2 | |
+----+------+-----+---------+-------+
3 rows in set

可以看到只有一列id了,因为student与class两张表中相同的id列自动合并了,相当于内连接

SELECT * FROM student INNER JOIN class ON student.id = class.id

如果更改class表的cname字段名称为name会出现什么情况呢?

mysql> ALTER TABLE class CHANGE cname name VARCHAR(10);
Query OK, 3 rows affected
Records: 3 Duplicates: 0 Warnings: 0 mysql> SELECT * FROM student NATURAL JOIN class; -- 因为两张表同名字段有两个,所有结果为空
Empty set

由于现在student与class表有两个同名的字段,所有结果为空

MySQL学习(四) SQL连接查询的更多相关文章

  1. MySQL 学习四 SQL优化

    MySQL逻辑架构: 第一层:客户端层,连接处理,授权认证,安全等功能.   第二层:核心层,查询解析,分析,优化,缓存,内置函数(时间,数学,加密),存储过程,触发器,视图   第三层:存储引擎.负 ...

  2. 深入学习之mysql(五)连接查询

    深入学习Mysql(五)连接查询 1.准备数据库: CREATE DATABASE IF NOT EXISTS `db_book2` DEFAULT CHARACTER SET UTF8; USE ` ...

  3. sql连接查询(inner join、full join、left join、 right join)

    sql连接查询(inner join.full join.left join. right join) 一.内连接(inner join) 首先我这有两张表 1.顾客信息表customer 2.消费订 ...

  4. SQLServer SQL连接查询深度探险(摘录

    SQL连接查询深度探险[摘录] 测试环境: Windows XP Profession MySQL 5.0.45 Oracle 9i DB2 UDB 9.1 测试的SQL脚本如下:此脚本适合MySQL ...

  5. MySQL学习(一)——Java连接MySql数据库

    MySQL学习(一)——Java连接MySql数据库 API详解: 获得语句执行 String sql = "Insert into category(cid, cname) values( ...

  6. 浅谈MySQL中优化sql语句查询常用的30种方法 - 转载

    浅谈MySQL中优化sql语句查询常用的30种方法 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中使 ...

  7. mysql统计类似SQL语句查询次数

    mysql统计类似SQL语句查询次数 vc-mysql-sniffer 工具抓取的sql分析. 1.先用shell脚本把所有enter符号替换为null,再根据语句前后的字符分隔语句 grep -Ev ...

  8. sql连接查询中的分类

    sql连接查询中的分类 1.内连接(结果不保留表中未对应的数据) 1.1等值连接:关联条件的运算符是用等号来连接的. 1.2不等值连接:连接条件是出等号之外的操作符 1.3自然连接:特殊的等值连接,在 ...

  9. python之MySQL学习——防止SQL注入

    python之MySQL学习——防止SQL注入 学习了:https://www.cnblogs.com/xiaomingzaixian/p/7126840.html https://www.cnblo ...

随机推荐

  1. s31 zabbix监控企业级监控

    zabbix 简介与监控 zabbix安装部署 zabbix配置主机监控 zabbix 自定义监控 zabbix 配置报警方式 网站服务全面监控 zabbix 自动发现与snmp监控

  2. Pycharm的激活码,亲测可用(20181223)

    K03CHKJCFT-eyJsaWNlbnNlSWQiOiJLMDNDSEtKQ0ZUIiwibGljZW5zZWVOYW1lIjoibnNzIDEwMDEiLCJhc3NpZ25lZU5hbWUiO ...

  3. 消息中间件——RabbitMQ

    RabbitMQ介绍 RabbitMQ是实现AMQP(高级消息队列协议)的消息中间件的一种,最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性.扩展性.高可用性等方面表现不俗.RabbitM ...

  4. C#+ZXing.dll生成手机路径导航二维码

    1.原谅我先写点废话哈 这两天用C#写一个C端的软件,甲方提出一个很无理的需求(在C端的程序中实现路径导航,关键是这个程序最终是运行在物理隔绝的电脑上的……),头疼了好几天,领导突然想到可以把坐标+百 ...

  5. 在 Linux 上如何挂载 qcow2 磁盘镜像

    1.下载qemu-nbd工具 sudo apt-get install qemu-utils 或者 sudo yum install qemu-img 2.加载nbd模块,然后挂载 sudo modp ...

  6. linux安装nodejs运行vue程序

    linux安装nodejs运行vue程序 1.与node官网下载安装包 https://nodejs.org/zh-cn/download/ 6.上传到服务器,并解压 tar -xvf node-v1 ...

  7. 处理返回键劫持(结合vue)

    在这里记录一下近期解决的一个问题 需求,在某个页面,浏览器返回按钮点击的时候,不能走浏览器的默认返回操作,而是要走自己的逻辑, 比如跳转页面等等. 那么问题来了,如何去不走默认返回呢.经过网上搜罗和同 ...

  8. 深度学习python的配置(Windows)

    Windows下深度学习python的配置 1.安装包的下载 (1)anaconda (2)pycharm 2.安装教程 (1)anaconda a.降版本 b.换源 (2)pycharm a.修改h ...

  9. Java 项目UML反向工程转化工具

    今天在看一个模拟器的源码,一个包里有多个类,一个类里又有多个属性和方法,如果按顺序看下来,不仅不能对整个模拟器的框架形成一个大致的认识,而且只会越看越混乱,所以,想到有没有什么工具可以将这些个类以及它 ...

  10. linux/cmd中python路径导入ModuleNotFoundError: No module named 'xxx'

    在linux或者直接在cmd中运行python文件时 会遇到导包错误的情况ModuleNotFoundError: No module named 'xxx’由于不在pycharm中 所以这里不能将上 ...