MySQL表的内外连接(重点)
目录
一、概述
二、内连接(INNER JOIN)
1、概念
2、语法格式
说明:
3、示例演示
需求: 显示SMITH的员工姓名和所在部门名称
传统写法(隐式内连接):
标准内连接写法(显式内连接):
三、外连接(OUTER JOIN)
1、概述
2、左外连接(LEFT JOIN)
概念
语法
说明:
示例演示
3、右外连接(RIGHT JOIN)
概念
语法
说明:
示例演示
四、综合练习
练习需求: 列出部门名称和对应部门的员工信息,同时列出没有员工的部门(使用数据库scott)
方法一:使用左外连接
方法二:使用右外连接
五、总结
一、概述
在数据库查询中,表的连接是将多个表中的数据按照某种关联条件进行组合的操作。主要分为内连接和外连接两大类。
二、内连接(INNER JOIN)
1、概念
内连接实际上是通过WHERE子句对两种表形成的笛卡尔积进行筛选,只返回满足连接条件的记录。我们之前学习的大多数查询都属于内连接,这也是开发过程中使用最频繁的连接方式。
2、语法格式
SELECT 字段
FROM 表1
INNER JOIN 表2 ON 连接条件 [AND 其他条件];
说明:
-
SQL中大写的表示关键字,[ ]中代表的是可选项。
-
内连接的条件通过
连接条件
指明,用户的其他筛选条件通过其他条件
指明。
3、示例演示
需求: 显示SMITH的员工姓名和所在部门名称
给出一张员工表和一张部门表,员工表中的ename代表的是员工的姓名,deptno代表的是员工所在部门的部门号。如下:
部门表中的dname代表的是部门名,deptno代表的是部门的部门号。如下:
传统写法(隐式内连接):
现在要显示SMITH的名字和其所在部门的名称,按照复合查询的做法就是,取员工表和部门表的笛卡尔积,在where子句中指明筛选条件为员工的部门号等于部门的部门号,筛选出每个员工匹配的部门信息,并指明员工姓名为SMITH,筛选出SMITH的信息和其所在部门的信息。如下:
SELECT ename, dname
FROM emp, dept
WHERE emp.deptno = dept.deptno AND ename = 'SMITH';
实际上述多表查询的方式本质就是内连接,用标准的内连接SQL编写:
-
将员工表和部门号放在from子句中并通过inner join关键字隔开。
-
在on子句后指明内连接的条件为员工的部门号等于部门的部门号,保证筛选出来的数据是有意义的。
-
在and之后指明筛选条件为员工的姓名为SMITH。
这样筛选出来的结果和多表查询筛选出来的结果是一样的,只不过是写法有一点不同而已。如下:
标准内连接写法(显式内连接):
SELECT ename, dname
FROM emp
INNER JOIN dept ON emp.deptno = dept.deptno AND ename = 'SMITH';
注意: 两种写法的查询结果是完全相同的,但显式内连接的语法更加清晰易懂。
三、外连接(OUTER JOIN)
1、概述
外连接用于查询不仅包含符合连接条件的记录,还包含其中一个表或两个表中的所有记录,即使在另一个表中没有匹配的记录。外连接主要分为左外连接和右外连接。
2、左外连接(LEFT JOIN)
概念
左外连接会返回左表(表1)中的所有记录,以及右表(表2)中满足连接条件的记录。如果右表中没有匹配的记录,则结果集中右表字段显示为NULL。
语法
SELECT 字段名
FROM 表名1
LEFT JOIN 表名2 ON 连接条件;
说明:
-
SQL中大写的表示关键字,[ ]中代表的是可选项。
-
左外连接的条件通过
连接条件
指明,用户的其他筛选条件通过其他条件
指明。
示例演示
创建测试表:(两张)
给出一张学生表和一张成绩表,学生表中的name代表的是学生的姓名,id代表的是学生的学号。如下:
-- 学生表
CREATE TABLE stu (id INT, name VARCHAR(30));
INSERT INTO stu VALUES(1,'jack'),(2,'tom'),(3,'kity'),(4,'nono');
成绩表中的id代表的是考试学生的学号,grade代表的是学生的成绩。如下:
-- 成绩表
CREATE TABLE exam (id INT, grade INT);
INSERT INTO exam VALUES(1, 56),(2,76),(11, 8);
查询需求: 查询所有学生的成绩,即使学生没有成绩,也要显示其个人信息
假如:现在要显示所有学生的成绩,如果直接使用内连接将学生表和成绩表连接起来,然后筛选出学生学号等于考试学生学号的记录,那么只能筛选出有考试成绩的学生信息。如下:
select * from stu inner join exam on stu.id=exam.id;
而查询需求是将没有成绩的学生的个人信息也要显示出来,也就是学生表当中的内容需要完全被显示出来。如果在连接学生表和成绩表时将学生表放在左侧,那么就可以使用左外连接,这时如果左侧表中的某条记录根据连接条件没有找到匹配的右侧表中的记录,就会直接显示左侧表中的记录信息,而其对应的右侧表中的列信息将会用NULL值进行填充。如下:
SELECT *
FROM stu
LEFT JOIN exam ON stu.id = exam.id;
查询所有学生的成绩,如果这个学生没有成绩,也要将学生的个人信息显示出来:
查询结果说明: 该查询会显示所有学生的信息,对于没有考试成绩的学生(如id为3和4的学生),成绩相关的字段会显示为NULL。
3、右外连接(RIGHT JOIN)
概念
右外连接会返回右表(表2)中的所有记录,以及左表(表1)中满足连接条件的记录。如果左表中没有匹配的记录,则结果集中左表字段显示为NULL。
语法
SELECT 字段
FROM 表名1
RIGHT JOIN 表名2 ON 连接条件;
说明:
-
SQL中大写的表示关键字,[ ]中代表的是可选项。
-
左外连接的条件通过
连接条件
指明,用户的其他筛选条件通过其他条件
指明。
示例演示
查询需求: 对stu表和exam表联合查询,显示所有成绩信息,即使该成绩没有对应的学生信息
题目要求将没有学生与它对应的成绩信息也要显示出来,也就是成绩表当中的内容需要完全被显示出来。如果在连接学生表和成绩表时将成绩表放在右侧,那么就可以使用右外连接,这时如果右侧表中的某条记录根据连接条件没有找到匹配的左侧表中的记录,就会直接显示右侧表中的记录信息,而其对应的左侧表中的信息将会用NULL值进行填充。如下:
SELECT *
FROM stu
RIGHT JOIN exam ON stu.id = exam.id;
查询结果说明: 该查询会显示所有考试成绩,对于没有对应学生信息的成绩(如id为11的成绩),学生信息字段会显示为NULL。
四、综合练习
练习需求: 列出部门名称和对应部门的员工信息,同时列出没有员工的部门(使用数据库scott)
由于题目要求同时列出部门名和员工信息,因此需要将部门表和员工表连接起来,连接条件就是部门的部门号要等于员工所在的部门号。如果直接使用内连接进行查询,那么将会显示出所有满足连接条件的记录。如下:
select dname,emp.* from dept inner join emp on dept.deptno=emp.deptno;
方法一:使用左外连接
而题目要求同时列出没有员工的部门,也就是部门表当中的内容需要完全被显示出来,如果在连接部门表和员工表时将部门表放在左侧,那么就可以使用左外连接。如下:
SELECT d.dname, e.*
FROM dept d
LEFT JOIN emp e ON d.deptno = e.deptno;
方法二:使用右外连接
当然,如果要使用右外连接,那么可以在连接部门表和员工表时将部门表放在右侧。如下:
SELECT d.dname, e.*
FROM emp e
RIGHT JOIN dept d ON d.deptno = e.deptno;
说明: 两种方法的结果相同,只是思考角度不同。左外连接以部门表为主表,右外连接以员工表为主表但将部门表放在右侧,本质上都是要确保部门表的完整性。
五、总结
-
内连接:只返回两个表中匹配的记录
-
左外连接:返回左表所有记录和右表匹配的记录
-
右外连接:返回右表所有记录和左表匹配的记录
-
实际开发中,根据业务需求选择合适的连接方式,确保数据的完整性和准确性