MySQL内外连接详解

表的连接分类

表的连接主要分为内连接和外连接两种类型。

内连接

内连接实际上就是利用WHERE子句对两种表形成的笛卡尔积进行筛选,这是我们前面学习的主要查询方式,也是开发过程中使用最多的连接查询。

我们除了可以使用" , "来隔离表,我们还可以使用下面的语法:和我们之前笛卡尔积,后面使用where条件筛选是一样的效果的!只不过下面的写法是比较标准的!

sql 复制代码
SELECT 字段 FROM 表1 INNER JOIN 表2 ON 连接条件 AND 其他条件;

前面学习的大部分查询都属于内连接。

案例:显示SMITH的名字和部门名称

传统写法:

sql 复制代码
SELECT ename, dname FROM EMP, DEPT WHERE EMP.deptno=DEPT.deptno AND ename='SMITH';
sql 复制代码
mysql> select emp.ename, dept.dname from emp, dept where emp.deptno=dept.deptno and emp.ename='SMITH';
+-------+----------+
| ename | dname    |
+-------+----------+
| SMITH | RESEARCH |
+-------+----------+
1 row in set (0.00 sec)

标准内连接写法:

sql 复制代码
SELECT ename, dname FROM EMP INNER JOIN DEPT ON EMP.deptno=DEPT.deptno AND ename='SMITH';
sql 复制代码
mysql> select emp.ename, dept.dname from emp inner join dept on emp.deptno=dept.deptno and emp.ename='SMITH';
+-------+----------+
| ename | dname    |
+-------+----------+
| SMITH | RESEARCH |
+-------+----------+
1 row in set (0.00 sec)

外连接

外连接分为左外连接和右外连接。

为主的在哪一边,基本就是使用那一边的连接方式!--- 后面的练习部分体现!!!

左外连接

如果联合查询时,左侧的表完全显示(左侧的信息不要做任何的过滤和筛选,完全保留)(即使右侧没有匹配记录),我们就称为左外连接

仅仅将 inner join 改成了 left join

sql 复制代码
SELECT 字段名 FROM 表名1 LEFT JOIN 表名2 ON 连接条件

创建测试表:

sql 复制代码
CREATE TABLE stu (id INT, name VARCHAR(30)); -- 学生表
INSERT INTO stu VALUES(1,'jack'),(2,'tom'),(3,'kity'),(4,'nono');

CREATE TABLE exam (id INT, grade INT); -- 成绩表
INSERT INTO exam VALUES(1, 56),(2,76),(11, 8);

mysql> select * from stu;
+------+------+
| id   | name |
+------+------+
|    1 | jack |
|    2 | tom  |
|    3 | kity |
|    4 | nono |
+------+------+
4 rows in set (0.00 sec)

mysql> select * from exam;
+------+-------+
| id   | grade |
+------+-------+
|    1 |    56 |
|    2 |    76 |
|   11 |     8 |
+------+-------+
3 rows in set (0.00 sec)

查询所有学生的成绩,如果学生没有成绩也要显示个人信息:

sql 复制代码
SELECT * FROM stu LEFT JOIN exam ON stu.id=exam.id;
sql 复制代码
mysql> select * from stu left join exam on stu.id=exam.id;
+------+------+------+-------+
| id   | name | id   | grade |
+------+------+------+-------+
|    1 | jack |    1 |    56 |
|    2 | tom  |    2 |    76 |
|    3 | kity | NULL |  NULL |
|    4 | nono | NULL |  NULL |
+------+------+------+-------+
4 rows in set (0.00 sec)

这个查询会显示左边表的所有记录,即使右边表没有匹配的记录。

右外连接

如果联合查询时,右侧的表完全显示(即使左侧没有匹配记录),我们就称为右外连接。

sql 复制代码
SELECT 字段 FROM 表名1 RIGHT JOIN 表名2 ON 连接条件;

对stu表和exam表联合查询,显示所有成绩,即使没有对应学生:

sql 复制代码
SELECT * FROM stu RIGHT JOIN exam ON stu.id=exam.id;
sql 复制代码
mysql> select * from stu right join exam on stu.id=exam.id;
+------+------+------+-------+
| id   | name | id   | grade |
+------+------+------+-------+
|    1 | jack |    1 |    56 |
|    2 | tom  |    2 |    76 |
| NULL | NULL |   11 |     8 |
+------+------+------+-------+
3 rows in set (0.00 sec)

练习:

列出部门名称和这些部门的员工信息,同时列出没有员工的部门

方法一(使用左连接):

sql 复制代码
SELECT d.dname, e.* FROM dept d LEFT JOIN emp e ON d.deptno=e.deptno;
sql 复制代码
mysql> select d.dname, e.* from dept d left join emp e on d.deptno=e.deptno;
+------------+--------+--------+-----------+------+---------------------+---------+---------+--------+
| dname      | empno  | ename  | job       | mgr  | hiredate            | sal     | comm    | deptno |
+------------+--------+--------+-----------+------+---------------------+---------+---------+--------+
| ACCOUNTING | 007934 | MILLER | CLERK     | 7782 | 1982-01-23 00:00:00 | 1300.00 |    NULL |     10 |
| ACCOUNTING | 007839 | KING   | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 |    NULL |     10 |
| ACCOUNTING | 007782 | CLARK  | MANAGER   | 7839 | 1981-06-09 00:00:00 | 2450.00 |    NULL |     10 |
| RESEARCH   | 007902 | FORD   | ANALYST   | 7566 | 1981-12-03 00:00:00 | 3000.00 |    NULL |     20 |
| RESEARCH   | 007876 | ADAMS  | CLERK     | 7788 | 1987-05-23 00:00:00 | 1100.00 |    NULL |     20 |
| RESEARCH   | 007788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 00:00:00 | 3000.00 |    NULL |     20 |
| RESEARCH   | 007566 | JONES  | MANAGER   | 7839 | 1981-04-02 00:00:00 | 2975.00 |    NULL |     20 |
| RESEARCH   | 007369 | SMITH  | CLERK     | 7902 | 1980-12-17 00:00:00 |  800.00 |    NULL |     20 |
| SALES      | 007900 | JAMES  | CLERK     | 7698 | 1981-12-03 00:00:00 |  950.00 |    NULL |     30 |
| SALES      | 007844 | TURNER | SALESMAN  | 7698 | 1981-09-08 00:00:00 | 1500.00 |    0.00 |     30 |
| SALES      | 007698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 00:00:00 | 2850.00 |    NULL |     30 |
| SALES      | 007654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 |     30 |
| SALES      | 007521 | WARD   | SALESMAN  | 7698 | 1981-02-22 00:00:00 | 1250.00 |  500.00 |     30 |
| SALES      | 007499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 00:00:00 | 1600.00 |  300.00 |     30 |
| OPERATIONS |   NULL | NULL   | NULL      | NULL | NULL                |    NULL |    NULL |   NULL |
+------------+--------+--------+-----------+------+---------------------+---------+---------+--------+
15 rows in set (0.00 sec)

方法二(使用右连接):

sql 复制代码
SELECT d.dname, e.* FROM emp e RIGHT JOIN dept d ON d.deptno=e.deptno;
sql 复制代码
mysql> select d.dname, e.* from emp e right join dept d on d.deptno=e.deptno;
+------------+--------+--------+-----------+------+---------------------+---------+---------+--------+
| dname      | empno  | ename  | job       | mgr  | hiredate            | sal     | comm    | deptno |
+------------+--------+--------+-----------+------+---------------------+---------+---------+--------+
| ACCOUNTING | 007934 | MILLER | CLERK     | 7782 | 1982-01-23 00:00:00 | 1300.00 |    NULL |     10 |
| ACCOUNTING | 007839 | KING   | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 |    NULL |     10 |
| ACCOUNTING | 007782 | CLARK  | MANAGER   | 7839 | 1981-06-09 00:00:00 | 2450.00 |    NULL |     10 |
| RESEARCH   | 007902 | FORD   | ANALYST   | 7566 | 1981-12-03 00:00:00 | 3000.00 |    NULL |     20 |
| RESEARCH   | 007876 | ADAMS  | CLERK     | 7788 | 1987-05-23 00:00:00 | 1100.00 |    NULL |     20 |
| RESEARCH   | 007788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 00:00:00 | 3000.00 |    NULL |     20 |
| RESEARCH   | 007566 | JONES  | MANAGER   | 7839 | 1981-04-02 00:00:00 | 2975.00 |    NULL |     20 |
| RESEARCH   | 007369 | SMITH  | CLERK     | 7902 | 1980-12-17 00:00:00 |  800.00 |    NULL |     20 |
| SALES      | 007900 | JAMES  | CLERK     | 7698 | 1981-12-03 00:00:00 |  950.00 |    NULL |     30 |
| SALES      | 007844 | TURNER | SALESMAN  | 7698 | 1981-09-08 00:00:00 | 1500.00 |    0.00 |     30 |
| SALES      | 007698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 00:00:00 | 2850.00 |    NULL |     30 |
| SALES      | 007654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 |     30 |
| SALES      | 007521 | WARD   | SALESMAN  | 7698 | 1981-02-22 00:00:00 | 1250.00 |  500.00 |     30 |
| SALES      | 007499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 00:00:00 | 1600.00 |  300.00 |     30 |
| OPERATIONS |   NULL | NULL   | NULL      | NULL | NULL                |    NULL |    NULL |   NULL |
+------------+--------+--------+-----------+------+---------------------+---------+---------+--------+
15 rows in set (0.00 sec)

实战OJ题目

相关推荐
宋大水1 小时前
【大作业-12】草莓成熟度检测模型,YOLO+PyQt+MySQL
数据库·深度学习·mysql·yolo·目标检测·pyqt·课程设计
_代号0071 小时前
MySQL梳理四:事务日志机制和多版本并发控制(MVCC)
mysql
赵_|大人2 小时前
Qt 自动无法加载数据库为空
开发语言·数据库·qt
2501_920047032 小时前
Mysql-事务
数据库·mysql·oracle
sukalot2 小时前
window显示驱动开发—将加密会话与 DirectX 视频加速器 2.0 解码器配合使用
数据库·驱动开发·音视频
笑衬人心。2 小时前
MySQL 如何优化慢查询
数据库·mysql
码明2 小时前
43.MySQL管理
数据库·sql·mysql
春时似衿里3 小时前
【Navicat 连接MySQL时出现错误1251:客户端不支持服务器请求的身份验证协议;请考虑升级MySQL客户端】
服务器·数据库·mysql
帅帅梓3 小时前
Linux lvm逻辑卷管理
linux·运维·数据库