MySQL-联合查询

1.简介

1.1为什么要使用联合查询

在数据设计时由于范式的要求,数据被拆分到多个表中,那么要查询⼀个条数据的完整信息,就
要从多个表中获取数据,如下图所⽰:要获取学⽣的基本信息和班级信息就要从学⽣表和班级表中获取,这时就需要使⽤联合查询,这⾥的联合指的是多个表的组合。

 1.2多表联合查询时MYSQL内部是如何进行计算的

参与查询的所有表取笛卡儿积,结果集在临时表中

 观察哪些记录是有效数据,根据两个表的关联关系过滤掉⽆效数据

 如果联合查询表的个数越多,表中的数据量越⼤,临时表就会越⼤,所以根据实际情况确定联合查询表的个数

1.3构造练习案例数据

# 课程表
insert into course (name) values ('Java'), ('C++'), ('MySQL'), ('操作系统'), ('计
算机⽹络'), ('数据结构');# 班级表
insert into class(name) values ('Java001班'), ('C++001班'), ('前端001班');# 学⽣表
insert into student (name, sno, age, gender, enroll_date, class_id) values
('唐三藏', '100001', 18, 1, '1986-09-01', 1),
('孙悟空', '100002', 18, 1, '1986-09-01', 1),
('猪悟能', '100003', 18, 1, '1986-09-01', 1),
('沙悟净', '100004', 18, 1, '1986-09-01', 1),
('宋江', '200001', 18, 1, '2000-09-01', 2),
('武松', '200002', 18, 1, '2000-09-01', 2),
('李逹', '200003', 18, 1, '2000-09-01', 2),
('不想毕业', '200004', 18, 1, '2000-09-01', 2);# 成绩表
insert into score (score, student_id, course_id) values
(70.5, 1, 1),(98.5, 1, 3),(33, 1, 5),(98, 1, 6),
(60, 2, 1),(59.5, 2, 5),
(33, 3, 1),(68, 3, 3),(99, 3, 5),
(67, 4, 1),(23, 4, 3),(56, 4, 5),(72, 4, 6),
(81, 5, 1),(37, 5, 5),
(56, 6, 2),(43, 6, 4),(79, 6, 6),
(80, 7, 2),(92, 7, 6);

1.4案例:一个完整的联合查询的过程

查询学生姓名为孙悟空的详细信息,包括学生个人信息和班级信息

1.确定参与查询的表,学生表和班级表

# 在from后同时写所有参与查询的表,并⽤逗号隔开
mysql> select * from student, class;
+----+--------------+--------+------+--------+-------------+----------+----+---
-----------+
| id | name | sno | age | gender | enroll_date | class_id | id | name |
+----+--------------+--------+------+--------+-------------+----------+----+---
-----------+
| 1 | 唐三藏 | 100001 | 18 | 1 | 1986-09-01 | 1 | 3 | 前端001班 |
| 1 | 唐三藏 | 100001 | 18 | 1 | 1986-09-01 | 1 | 2 | C++001班 |
| 1 | 唐三藏 | 100001 | 18 | 1 | 1986-09-01 | 1 | 1 | Java001班 |
| 2 | 孙悟空 | 100002 | 18 | 1 | 1986-09-01 | 1 | 3 | 前端001班 |
| 2 | 孙悟空 | 100002 | 18 | 1 | 1986-09-01 | 1 | 2 | C++001班 |
| 2 | 孙悟空 | 100002 | 18 | 1 | 1986-09-01 | 1 | 1 | Java001班 |
| 3 | 猪悟能 | 100003 | 18 | 1 | 1986-09-01 | 1 | 3 | 前端001班 |
| 3 | 猪悟能 | 100003 | 18 | 1 | 1986-09-01 | 1 | 2 | C++001班 |
| 3 | 猪悟能 | 100003 | 18 | 1 | 1986-09-01 | 1 | 1 | Java001班 |
| 4 | 沙悟净 | 100004 | 18 | 1 | 1986-09-01 | 1 | 3 | 前端001班 |
| 4 | 沙悟净 | 100004 | 18 | 1 | 1986-09-01 | 1 | 2 | C++001班 |
| 4 | 沙悟净 | 100004 | 18 | 1 | 1986-09-01 | 1 | 1 | Java001班 |
| 5 | 宋江 | 200001 | 18 | 1 | 2000-09-01 | 1 | 3 | 前端001班 |
| 5 | 宋江 | 200001 | 18 | 1 | 2000-09-01 | 1 | 2 | C++001班 |
| 5 | 宋江 | 200001 | 18 | 1 | 2000-09-01 | 1 | 1 | Java001班 |
| 6 | 武松 | 200002 | 18 | 1 | 2000-09-01 | 1 | 3 | 前端001班 |
| 6 | 武松 | 200002 | 18 | 1 | 2000-09-01 | 1 | 2 | C++001班 |
| 6 | 武松 | 200002 | 18 | 1 | 2000-09-01 | 1 | 1 | Java001班 |
| 7 | 李逹 | 200003 | 18 | 1 | 2000-09-01 | 1 | 3 | 前端001班 |
| 7 | 李逹 | 200003 | 18 | 1 | 2000-09-01 | 1 | 2 | C++001班 |
| 7 | 李逹 | 200003 | 18 | 1 | 2000-09-01 | 1 | 1 | Java001班 |
| 8 | 不想毕业 | 200004 | 18 | 1 | 2000-09-01 | 1 | 3 | 前端001班 |
| 8 | 不想毕业 | 200004 | 18 | 1 | 2000-09-01 | 1 | 2 | C++001班 |
| 8 | 不想毕业 | 200004 | 18 | 1 | 2000-09-01 | 1 | 1 | Java001班 |
+----+--------------+--------+------+--------+-------------+----------+----+---
-----------+
24 rows in set (0.00 sec)

2.确定连接条件,student表中的class_id与class表中id列的值相等

# 在where⼦句中加⼊连接条件
mysql> select * from student, class where student.class_id = class.id;
+----+--------------+--------+------+--------+-------------+----------+----+---
---------+
| id | name | sno | age | gender | enroll_date | class_id | id | name |
+----+--------------+--------+------+--------+-------------+----------+----+---
---------+
| 1 | 唐三藏 | 100001 | 18 | 1 | 1986-09-01 | 1 | 1 | Java001班 |
| 2 | 孙悟空 | 100002 | 18 | 1 | 1986-09-01 | 1 | 1 | Java001班 |
| 3 | 猪悟能 | 100003 | 18 | 1 | 1986-09-01 | 1 | 1 | Java001班 |
| 4 | 沙悟净 | 100004 | 18 | 1 | 1986-09-01 | 1 | 1 | Java001班 |
| 5 | 宋江 | 200001 | 18 | 1 | 2000-09-01 | 1 | 1 | Java001班 |
| 6 | 武松 | 200002 | 18 | 1 | 2000-09-01 | 1 | 1 | Java001班 |
| 7 | 李逹 | 200003 | 18 | 1 | 2000-09-01 | 1 | 1 | Java001班 |
| 8 | 不想毕业 | 200004 | 18 | 1 | 2000-09-01 | 1 | 1 | Java001班 |
+----+--------------+--------+------+--------+-------------+----------+----+---
---------+
8 rows in set (0.00 sec)

3.加入查询条件

# 依题意添加where条件
mysql> select * from student, class where student.class_id = class.id and name 
= '宋江';
ERROR 1052 (23000): Column 'name' in where clause is ambiguous# 由于两个表中都有name列,所以MySQL不清楚具体要使⽤哪个列,这时可以⽤“表名.列号”的⽅式指
定具体的列
# 得到⽬标记录⾏mysql> select * from student, class where student.class_id = class.id and
student.name = '宋江';
+----+--------+--------+------+--------+-------------+----------+----+------------+
| id | name | sno | age | gender | enroll_date | class_id | id | name  |
+----+--------+--------+------+--------+-------------+----------+----+------------+
| 5 | 宋江 | 200001 | 18 | 1 | 2000-09-01 | 1 | 1 | Java001班 |
+----+--------+--------+------+--------+-------------+----------+----+------------+
1 row in set (0.00 sec)

4.精减查询结果字段

selectstudent.id, student.name, student.sno, student.age, student.gender, student.enroll_date, class.name 
fromstudent, class 
wherestudent.class_id = class.id 
andstudent.name = '宋江';
+----+--------+--------+------+--------+-------------+------------+
| id | name | sno | age | gender | enroll_date | name |
+----+--------+--------+------+--------+-------------+------------+
| 5 | 宋江 | 200001 | 18 | 1 | 2000-09-01 | Java001班 |
+----+--------+--------+------+--------+-------------+------------+
1 row in set (0.00 sec)

5.可以为表名指定别名

selects.id, s.name, s.sno, s.age, s.gender, s.enroll_date, c.name 
fromstudent s , class c 
wheres.class_id = c.id 
ands.name = '宋江';+----+--------+--------+------+--------+-------------+------------+
| id | name | sno | age | gender | enroll_date | name |
+----+--------+--------+------+--------+-------------+------------+
| 5 | 宋江 | 200001 | 18 | 1 | 2000-09-01 | Java001班 |
+----+--------+--------+------+--------+-------------+------------+
1 row in set (0.00 sec)

2.内连接

2.1语法

select 字段 from 表1 别名1, 表2 别名2 where 连接条件 and 其他条件;select 字段 from 表1 别名1 [inner] join 表2 别名2 on 连接条件 where 其他条件;

2.2示例

查询“唐三藏”同学的成绩

mysql> select s.name, sc.score from student s join score sc on sc.student_id = 
s.id where s.name = '唐三藏';
+-----------+-------+
| name | score |
+-----------+-------+
| 唐三藏 | 70.5 |
| 唐三藏 | 98.5 |
| 唐三藏 | 33 |
| 唐三藏 | 98 |
+-----------+-------+
4 rows in set (0.00 sec)
查询所有同学的总成绩,及同学的个⼈信息
mysql> select s.name, sum(sc.score) from student s, score sc where
sc.student_id = s.id group by (s.id);
+-----------+---------------+
| name | sum(sc.score) |
+-----------+---------------+
| 唐三藏 | 300 |
| 孙悟空 | 119.5 |
| 猪悟能 | 200 |
| 沙悟净 | 218 |
| 宋江 | 118 |
| 武松 | 178 |
| 李逹 | 172 |
+-----------+---------------+
7 rows in set (0.00 sec)

Group by使用了student.id进行分组,查询表列表中的student.name没有出现在Group by分组中,也没有包含在聚合函数中,这是因为SQL规定在Group by分组查询时,如果查询列表中的列没 有出现在GROUP BY⼦句中,但这些列的值在每个分组内部是相同的,那么它们可以出现在查询结果中。

 查询所有同学每⻔课的成绩,及同学的个⼈信息

selects.id as id,s.name as 姓名,s.sno as 学号,s.gender as 性别,c.name as 班级,sc.score as 分数
fromstudent s, course c, score sc
wheres.id = sc.student_id
andc.id = sc.course_id
order bys.id;
# 结果集中没有"不想毕业"同学的成绩,因为score表中没有这位同学的记录
+----+-----------+--------+--------+-----------------+--------+
| id | 姓名 | 学号 | 性别 | 班级 | 分数 |
+----+-----------+--------+--------+-----------------+--------+
| 1 | 唐三藏 | 100001 | 1 | Java | 70.5 |
| 1 | 唐三藏 | 100001 | 1 | MySQL | 98.5 |
| 1 | 唐三藏 | 100001 | 1 | 计算机⽹络 | 33 |
| 1 | 唐三藏 | 100001 | 1 | 数据结构 | 98 |
| 2 | 孙悟空 | 100002 | 1 | Java | 60 |
| 2 | 孙悟空 | 100002 | 1 | 计算机⽹络 | 59.5 |
| 3 | 猪悟能 | 100003 | 1 | Java | 33 |
| 3 | 猪悟能 | 100003 | 1 | MySQL | 68 |
| 3 | 猪悟能 | 100003 | 1 | 计算机⽹络 | 99 |
| 4 | 沙悟净 | 100004 | 1 | Java | 67 |
| 4 | 沙悟净 | 100004 | 1 | MySQL | 23 |
| 4 | 沙悟净 | 100004 | 1 | 计算机⽹络 | 56 |
| 4 | 沙悟净 | 100004 | 1 | 数据结构 | 72 |
| 5 | 宋江 | 200001 | 1 | Java | 81 |
| 5 | 宋江 | 200001 | 1 | 计算机⽹络 | 37 |
| 6 | 武松 | 200002 | 1 | C++ | 56 |
| 6 | 武松 | 200002 | 1 | 操作系统 | 43 |
| 6 | 武松 | 200002 | 1 | 数据结构 | 79 |
| 7 | 李逹 | 200003 | 1 | C++ | 80 |
| 7 | 李逹 | 200003 | 1 | 数据结构 | 92 |
+----+-----------+--------+--------+-----------------+--------+
20 rows in set (0.00 sec)

3.外连接

外连接分为左外连接、右外连接和全外连接三种类型,MySQL不⽀持全外连接。
左外连接:返回左表的所有记录和右表中匹配的记录。如果右表中没有匹配的记录,则结果集中对应字段会显⽰为NULL。
右外连接:与左外连接相反,返回右表的所有记录和左表中匹配的记录。如果左表中没有匹配的记录,则结果集中对应字段会显⽰为NULL。
全外连接:结合了左外连接和右外连接的特点,返回左右表中的所有记录。如果某⼀边表中没有匹配的记录,则结果集中对应字段会显⽰为NULL。

3.1语法

-- 左外连接,表1完全显⽰
select 字段名 from 表名1 left join 表名2 on 连接条件;
-- 右外连接,表2完全显⽰
select 字段 from 表名1 right join 表名2 on 连接条件;

3.2示例

查询没有参加考试的同学信息

# 左连接以JOIN左边的表为基准,左表显⽰全部记录,右表中没有匹配的记录⽤NULL填充
mysql> select s.id, s.name, s.sno, s.age, sc.* from student s LEFT JOIN score 
sc on sc.student_id = s.id;
+----+--------------+--------+------+------+-------+------------+-----------+
| id | name | sno | age | id | score | student_id | course_id |
+----+--------------+--------+------+------+-------+------------+-----------+
| 1 | 唐三藏 | 100001 | 18 | 1 | 70.5 | 1 | 1 |
| 1 | 唐三藏 | 100001 | 18 | 2 | 98.5 | 1 | 3 |
| 1 | 唐三藏 | 100001 | 18 | 3 | 33 | 1 | 5 |
| 1 | 唐三藏 | 100001 | 18 | 4 | 98 | 1 | 6 |
| 2 | 孙悟空 | 100002 | 18 | 5 | 60 | 2 | 1 |
| 2 | 孙悟空 | 100002 | 18 | 6 | 59.5 | 2 | 5 |
| 3 | 猪悟能 | 100003 | 18 | 7 | 33 | 3 | 1 |
| 3 | 猪悟能 | 100003 | 18 | 8 | 68 | 3 | 3 |
| 3 | 猪悟能 | 100003 | 18 | 9 | 99 | 3 | 5 |
| 4 | 沙悟净 | 100004 | 18 | 10 | 67 | 4 | 1 |
| 4 | 沙悟净 | 100004 | 18 | 11 | 23 | 4 | 3 |
| 4 | 沙悟净 | 100004 | 18 | 12 | 56 | 4 | 5 |
| 4 | 沙悟净 | 100004 | 18 | 13 | 72 | 4 | 6 |
| 5 | 宋江 | 200001 | 18 | 14 | 81 | 5 | 1 |
| 5 | 宋江 | 200001 | 18 | 15 | 37 | 5 | 5 |
| 6 | 武松 | 200002 | 18 | 16 | 56 | 6 | 2 |
| 6 | 武松 | 200002 | 18 | 17 | 43 | 6 | 4 |
| 6 | 武松 | 200002 | 18 | 18 | 79 | 6 | 6 |
| 7 | 李逹 | 200003 | 18 | 19 | 80 | 7 | 2 |
| 7 | 李逹 | 200003 | 18 | 20 | 92 | 7 | 6 |
| 8 | 不想毕业 | 200004 | 18 | NULL | NULL | NULL | NULL |
+----+--------------+--------+------+------+-------+------------+-----------+
21 rows in set (0.00 sec)# 过滤参加了考试的同学
mysql> select s.* from student s LEFT JOIN score sc on sc.student_id = s.id 
where sc.score is null;
+----+--------------+--------+------+--------+-------------+----------+
| id | name | sno | age | gender | enroll_date | class_id |
+----+--------------+--------+------+--------+-------------+----------+
| 8 | 不想毕业 | 200004 | 18 | 1 | 2000-09-01 | 1 |
+----+--------------+--------+------+--------+-------------+----------+
1 row in set (0.00 sec)
查询没有学⽣的班级
# 右连接以JOIN右边的表为基准,右表显⽰全部记录,左表中没有匹配的记录⽤NULL填充
mysql> select * from student s RIGHT JOIN class c on c.id = s.class_id;
+------+--------------+--------+------+--------+-------------+----------+----+--------------+
| id | name | sno | age | gender | enroll_date | class_id | id | name |
+------+--------------+--------+------+--------+-------------+----------+----+--------------+
| 4 | 沙悟净 | 100004 | 18 | 1 | 1986-09-01 | 1 | 1 | Java001班 |
| 3 | 猪悟能 | 100003 | 18 | 1 | 1986-09-01 | 1 | 1 | Java001班 |
| 2 | 孙悟空 | 100002 | 18 | 1 | 1986-09-01 | 1 | 1 | Java001班 |
| 1 | 唐三藏 | 100001 | 18 | 1 | 1986-09-01 | 1 | 1 | Java001班 |
| 8 | 不想毕业 | 200004 | 18 | 1 | 2000-09-01 | 2 | 2 | C++001班 |
| 7 | 李逹 | 200003 | 18 | 1 | 2000-09-01 | 2 | 2 | C++001班 |
| 6 | 武松 | 200002 | 18 | 1 | 2000-09-01 | 2 | 2 | C++001班 |
| 5 | 宋江 | 200001 | 18 | 1 | 2000-09-01 | 2 | 2 | C++001班 |
| NULL | NULL | NULL | NULL | NULL | NULL | NULL | 3 | 前端001班 |
+------+--------------+--------+------+--------+-------------+----------+----+--------------+# 过滤有学⽣的班级
mysql> select c.* from student s RIGHT JOIN class c on c.id = s.class_id where
s.id is null;
+----+--------------+
| id | name |
+----+--------------+
| 3 | 前端001班 |
+----+--------------+
1 row in set (0.00 sec)

4.自连接

4.1应用场景

⾃连接是⾃⼰与⾃⼰取笛卡尔积,可以把⾏转化成列,在查询的时候可以使⽤where条件对结果进⾏ 过滤,或者说实现⾏与⾏之间的⽐较。在做表连接时为表起不同的别名。
# 不为表指定别名
mysql> select * from score, score;
ERROR 1066 (42000): Not unique table/alias: 'score'# 指定别名
mysql> select * from score s1, score s2;

4.2示例

显示所有“MySQL”成绩比“JAVA”成绩高的成绩信息

# ⾸先分两步进⾏,先查出JAVA和MySQL的课程Id,分别为1和3
mysql> select * from course where name = 'Java' or name = 'MySQL';
+----+-------+
| id | name |
+----+-------+
| 1 | Java |
| 3 | MySQL |
+----+-------+
2 rows in set (0.00 sec)# 再查询成绩表中,JAVA成绩⽐MySQL成绩好的信息
mysql> select s1.* from score s1, score s2 where s1.student_id = s2.student_id 
and s1.course_id = 3 and s2.course_id = 1 and s1.score > s2.score;
+----+-------+------------+-----------+
| id | score | student_id | course_id |
+----+-------+------------+-----------+
| 2 | 98.5 | 1 | 3 |
| 8 | 68 | 3 | 3 |
+----+-------+------------+-----------+
2 rows in set (0.00 sec)# 结合在⼀起进⾏查询
select s1.* fromscore s1, score s2, course c1,course c2
wheres1.student_id = s2.student_id
ands1.course_id = c1.id
ands2.course_id = c2.id 
ands1.score > s2.score
andc1.`name` = 'MySQL'
andc2.`name` = 'Java';
+----+-------+------------+-----------+
| id | score | student_id | course_id |
+----+-------+------------+-----------+
|  2 |  98.5 |          1 |         3 |
|  8 |    68 |          3 |         3 |
+----+-------+------------+-----------+
2 rows in set (0.00 sec)

4.3表连接练习

显⽰所有"MySQL"成绩⽐"JAVA"成绩⾼的学⽣信息和班级以及成绩信息
# 相关的表全部加⼊连接,并确定连接条件
select stu.name as 姓名, c.name as 班级, s1.score as MySQL分数, s2.score as Java
分数 fromscore s1, score s2, course c1,course c2,student stu,class c
wheres1.student_id = s2.student_id
ands1.course_id = c1.id
ands2.course_id = c2.id 
ands1.score > s2.score
andstu.id = s1.student_id
andstu.class_id = c.id
andc1.`name` = 'MySQL'
andc2.`name` = 'Java';+-----------+------------+-------------+------------+
| 姓名 | 班级 | MySQL分数 | Java分数 |
+-----------+------------+-------------+------------+
| 唐三藏 | Java001班 | 98.5 | 70.5 |
| 猪悟能 | Java001班 | 68 | 33 |
+-----------+------------+-------------+------------+
2 rows in set (0.00 sec)

5.子查询

⼦查询是把⼀个SELECT语句的结果当做别⼀个SELECT语句的条件,也叫嵌套查询

5.1语法

select * from table1 where col_name1 {= | IN} (select col_name1 from table2 where col_name2 {= | IN} [(select ...)] ...
)

5.2单行子查询

嵌套的查询中只返回⼀⾏数据
⽰例:查询与"不想毕业"同学的同班同学
mysql> select * from student where class_id = (select class_id from student 
where name = '不想毕业');
+----+--------------+--------+------+--------+-------------+----------+
| id | name | sno | age | gender | enroll_date | class_id |
+----+--------------+--------+------+--------+-------------+----------+
| 5 | 宋江 | 200001 | 18 | 1 | 2000-09-01 | 2 |
| 6 | 武松 | 200002 | 18 | 1 | 2000-09-01 | 2 |
| 7 | 李逹 | 200003 | 18 | 1 | 2000-09-01 | 2 |
| 8 | 不想毕业 | 200004 | 18 | 1 | 2000-09-01 | 2 |
+----+--------------+--------+------+--------+-------------+----------+
4 rows in set (0.00 sec)

5.3多行子查询

嵌套的查询中返回多⾏数据,使⽤[NOT] IN关键字
⽰例:查询"MySQL"或"Java"课程的成绩信息
mysql> select * from score where course_id in (select id from course where
name = 'Java' or name = 'MySQL');
+----+-------+------------+-----------+
| id | score | student_id | course_id |
+----+-------+------------+-----------+
|  1 |  70.5 |          1 |         1 |
|  5 |    60 |          2 |         1 |
|  7 |    33 |          3 |         1 |
| 10 |    67 |          4 |         1 |
| 14 |    81 |          5 |         1 |
|  2 |  98.5 |          1 |         3 |
|  8 |    68 |          3 |         3 |
| 11 |    23 |          4 |         3 |
+----+-------+------------+-----------+
8 rows in set (0.00 sec)
# 使⽤NOT IN 可以查询除了"MySQL"或"Java"课程的成绩
mysql> select * from score where course_id not in (select id from course where
name = 'Java' or name = 'MySQL');
+----+-------+------------+-----------+
| id | score | student_id | course_id |
+----+-------+------------+-----------+
|  3 |    33 |          1 |         5 |
|  4 |    98 |          1 |         6 |
|  6 |  59.5 |          2 |         5 |
|  9 |    99 |          3 |         5 |
| 12 |    56 |          4 |         5 |
| 13 |    72 |          4 |         6 |
| 15 |    37 |          5 |         5 |
| 16 |    56 |          6 |         2 |
| 17 |    43 |          6 |         4 |
| 18 |    79 |          6 |         6 |
| 19 |    80 |          7 |         2 |
| 20 |    92 |          7 |         6 |
+----+-------+------------+-----------+
12 rows in set (0.00 sec)

5.4多列子查询

单⾏⼦查询和多⾏⼦查询都只返回⼀列数据,多列⼦查询中可以返回多个列的数据,外层查询与嵌套 的内层查询的列要匹配
⽰例:查询重复录⼊的分数
# 插⼊重复的分数:score, student_id, course_id列重复
mysql> insert into score(score, student_id, course_id) values
(70.5, 1, 1),(98.5, 1, 3),(60, 2, 1);
# ⼦查询中返回多个列
mysql> SELECT * FROM score WHERE (score, student_id, course_id ) IN ( SELECT score, student_id,course_id FROM score GROUP BY score, student_id, course_id HAVINGcount( 0 ) > 1);+----+-------+------------+-----------+
| id | score | student_id | course_id |
+----+-------+------------+-----------+
|  1 |  70.5 |          1 |         1 |
|  2 |  98.5 |          1 |         3 |
|  5 |    60 |          2 |         1 |
| 21 |  70.5 |          1 |         1 |
| 22 |  98.5 |          1 |         3 |
| 23 |    60 |          2 |         1 |
+----+-------+------------+-----------+
6 rows in set (0.00 sec)

5.5在from子句中使用子查询

当⼀个查询产⽣结果时,MySQL⾃动创建⼀个临时表,然后把结果集放在这个临时表中,最终返回 给⽤⼾,在from⼦句中也可以使⽤临时表进⾏⼦查询或表连接操作

 ⽰例:查询所有⽐"Java001班"平均分⾼的成绩信息

# ⾸先分步进⾏,第⼀步先查出Java001班的平均分
mysql> select avg(sc.score) score from student s join class c on s.class_id = c.id join score sc on s.id = sc.student_idwherec.name = 'Java001班';
+----------+
|    score |
+----------+
| 66.65625 |
+----------+
1 row in set (0.00 sec)
# 把以上查询做为临时表,与真实表进⾏⽐较
mysql> select * from score s, (select avg(sc.score) score from student s join class c on s.class_id = c.id join score sc on s.id = sc.student_idwherec.name = 'Java001班') tmp where s.score > tmp.score;
+----+-------+------------+-----------+----------+
| id | score | student_id | course_id |    score |
+----+-------+------------+-----------+----------+
|  1 |  70.5 |          1 |         1 | 66.65625 |
|  2 |  98.5 |          1 |         3 | 66.65625 |
|  4 |    98 |          1 |         6 | 66.65625 |
|  8 |    68 |          3 |         3 | 66.65625 |
|  9 |    99 |          3 |         5 | 66.65625 |
| 10 |    67 |          4 |         1 | 66.65625 |
| 13 |    72 |          4 |         6 | 66.65625 |
| 14 |    81 |          5 |         1 | 66.65625 |
| 18 |    79 |          6 |         6 | 66.65625 |
| 19 |    80 |          7 |         2 | 66.65625 |
| 20 |    92 |          7 |         6 | 66.65625 |
| 21 |  70.5 |          1 |         1 | 66.65625 |
| 22 |  98.5 |          1 |         3 | 66.65625 |
+----+-------+------------+-----------+----------+
13 rows in set (0.00 sec)
tmp 是临时表的别名

6.合并查询

在实际应⽤中,为了合并多个select操作返回的结果,可以使⽤集合操作符 union,union all

6.1创建新表并初始化数据

# 创建⼀个新表并初始化数据
mysql> create table student1 like student;
Query OK, 0 rows affected (0.03 sec)insert into student1 (name, sno, age, gender, enroll_date, class_id) values
('唐三藏', '100001', 18, 1, '1986-09-01', 1),
('刘备', '300001', 18, 1, '1993-09-01', 3),
('张⻜', '300002', 18, 1, '1993-09-01', 3),
('关⽻', '300003', 18, 1, '1993-09-01', 3);
Query OK, 4 rows affected (0.01 sec)
Records: 4 Duplicates: 0 Warnings:mysql> select * from student1;
+----+-----------+--------+------+--------+-------------+----------+
| id | name | sno | age | gender | enroll_date | class_id |
+----+-----------+--------+------+--------+-------------+----------+
| 1 | 唐三藏 | 100001 | 18 | 1 | 1986-09-01 | 1 |
| 2 | 刘备 | 300001 | 18 | 1 | 1993-09-01 | 3 |
| 3 | 张⻜ | 300002 | 18 | 1 | 1993-09-01 | 3 |
| 4 | 关⽻ | 300003 | 18 | 1 | 1993-09-01 | 3 |
+----+-----------+--------+------+--------+-------------+----------+
4 rows in set (0.00 sec)

6.2Union

该操作符⽤于取得两个结果集的并集。当使⽤该操作符时,会⾃动去掉结果集中的重复⾏。
⽰例:查询student表中 id < 3 的同学和student1表中的所有同学
# 结果集中有两张表中的数据,但是唐三藏只返回了⼀条记录
mysql> select * from student where id < 3 union select * from student1;
+----+-----------+--------+------+--------+-------------+----------+
| id | name | sno | age | gender | enroll_date | class_id |
+----+-----------+--------+------+--------+-------------+----------+
| 1 | 唐三藏 | 100001 | 18 | 1 | 1986-09-01 | 1 |
| 2 | 孙悟空 | 100002 | 18 | 1 | 1986-09-01 | 1 |
| 2 | 刘备 | 300001 | 18 | 1 | 1993-09-01 | 3 |
| 3 | 张⻜ | 300002 | 18 | 1 | 1993-09-01 | 3 |
| 4 | 关⽻ | 300003 | 18 | 1 | 1993-09-01 | 3 |
+----+-----------+--------+------+--------+-------------+----------+
5 rows in set (0.00 sec)

6.3 Union all

该操作符⽤于取得两个结果集的并集。当使⽤该操作符时,不会去掉结果集中的重复⾏。
# 结果集中有两张表中的数据,返回了所有唐三藏的记录
mysql> select * from student where id < 3 union all select * from student1;
+----+-----------+--------+------+--------+-------------+----------+
| id | name | sno | age | gender | enroll_date | class_id |
+----+-----------+--------+------+--------+-------------+----------+
| 1 | 唐三藏 | 100001 | 18 | 1 | 1986-09-01 | 1 |
| 2 | 孙悟空 | 100002 | 18 | 1 | 1986-09-01 | 1 |
| 1 | 唐三藏 | 100001 | 18 | 1 | 1986-09-01 | 1 |
| 2 | 刘备 | 300001 | 18 | 1 | 1993-09-01 | 3 |
| 3 | 张⻜ | 300002 | 18 | 1 | 1993-09-01 | 3 |
| 4 | 关⽻ | 300003 | 18 | 1 | 1993-09-01 | 3 |
+----+-----------+--------+------+--------+-------------+----------+
6 rows in set (0.00 sec)

7.插入查询结果

7.1语法

INSERT INTO table_name [(column [, column ...])] SELECT ...

7.2示例

将student表中C++001班的学⽣复制到student1表中
mysql> insert into student1 (name, sno, age, gender, enroll_date, class_id)select s.name, s.sno, s.age, s.gender, s.enroll_date, s.class_idfrom student s, class c where s.class_id = c.id and c.name = 'C++001班';Query OK, 4 rows affected (0.01 sec)Records: 4 Duplicates: 0 Warnings: 0mysql> select * from student1;+----+--------------+--------+------+--------+-------------+----------+| id | name | sno | age | gender | enroll_date | class_id |+----+--------------+--------+------+--------+-------------+----------+| 1 | 唐三藏 | 100001 | 18 | 1 | 1986-09-01 | 1 || 2 | 刘备 | 300001 | 18 | 1 | 1993-09-01 | 3 || 3 | 张⻜ | 300002 | 18 | 1 | 1993-09-01 | 3 || 4 | 关⽻ | 300003 | 18 | 1 | 1993-09-01 | 3 || 5 | 宋江 | 200001 | 18 | 1 | 2000-09-01 | 2 || 6 | 武松 | 200002 | 18 | 1 | 2000-09-01 | 2 || 7 | 李逹 | 200003 | 18 | 1 | 2000-09-01 | 2 || 8 | 不想毕业 | 200004 | 18 | 1 | 2000-09-01 | 2 |+----+--------------+--------+------+--------+-------------+----------+8 rows in set (0.00 sec

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/435316.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

全网最全软件测试面试题(含答案解析+文档)

一、软件测试基础面试题 1、阐述软件生命周期都有哪些阶段? 常见的软件生命周期模型有哪些? 软件生命周期是指一个计算机软件从功能确定设计&#xff0c;到开发成功投入使用&#xff0c;并在使用中不断地修改、增补和完善&#xff0c;直到停止该软件的使用的全过程(从酝酿到…

修改Opcenter EXFN 页面超时时间(Adjust UI Session Extend Token)

如果你想修改Opcenter EXFN中页面Session的超时时间&#xff0c;你可以按照如下步骤修改SessionAge 这个参数&#xff1a; 管理员运行CMD执行以下命令 umconf -getconfig -file C:\temp\config.json如果第2步有报错&#xff0c;则执行步骤4;如果没有报错则执行第5步如果第2步…

react-问卷星项目(2)

流程 husky 一个git hook 工具&#xff0c;即在git commit之前执行自定义的命令&#xff0c;将规范流程化&#xff0c;如执行代码风格的检查&#xff0c;避免提交非规范的代码&#xff0c;在github搜索即可。 这两条是接着执行的&#xff0c;表示创建husky&#xff0c;在文档…

C++【类和对象】(取地址运算符重载与实现Date类)

文章目录 取地址运算符重载const成员函数取地址运算符重载 Date类的实现Date.hDate.cpp1.检查日期合法性2. 构造函数/赋值运算符重载3.得到某月的天数4. Date类 - 天数的操作4.1 日期 天数4.2 日期 天数4.3 日期 - 天数4.4 日期 - 天数 5. Date的前后置/--5.1 前置5.2 后置5.…

fastadmin搜索刷新列表,怎么限制用户频繁点击?

文章目录 fastadmin搜索刷新列表&#xff0c;怎么限制用户频繁点击&#xff1f;解决方案fastadmin事件方法实现完结 fastadmin搜索刷新列表&#xff0c;怎么限制用户频繁点击&#xff1f; fastadmin目前有个很致命的问题&#xff0c;就是用户可以频繁的点击搜索等按钮&#xf…

Linux防火墙-nat表

作者介绍&#xff1a;简历上没有一个精通的运维工程师。希望大家多多关注作者&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 我们经过上小章节讲了Linux的部分进阶命令&#xff0c;我们接下来一章节来讲讲Linux防火墙。由于目前以云服务器为主&#x…

android kotlin Extension扩展函数

1、新建一个kt文件&#xff1a; 2、代码&#xff1a; class User(var name:String)/**扩展函数**/ fun User.Print(){print("用户名 $name") }// 扩展函数 swap,调换不同位置的值 fun MutableList<Int>.swap(index1: Int, index2: Int) {val tmp this[index1…

组合逻辑元件与时序逻辑元件

组合逻辑元件和时序逻辑元件都是数字电路中的基本构建块&#xff0c;但它们在功能和结构上存在显著差异。 1. 组合逻辑元件: 内容: 组合逻辑元件的输出仅取决于当前的输入&#xff0c;而与之前的输入无关。 它们没有记忆功能。 常见的组合逻辑元件包括&#xff1a; 与门 (AND…

Java_TestNg

TestNg 前言支持特性 使用步骤1.引入库 常用注解Test注解BeforeSuite AfterSuiteAfterClass BeforeClassAfterTest BeforeTestAfterGroups BeforeGroupsBeforeMethod AfterMethodDataProviderFactoryListenersPatameters断言相等 不相等true/falsenull / !nullequals / !equals…

【C++篇】启航——初识C++(上篇)

目录 引言 一、C的起源和发展史 1.起源 2.C版本更新 二、C在⼯作领域中的应⽤ 三、C入门建议 1.参考文档 2.推荐书籍 四、C的第一个程序 1.C语言写法 2.C写法 五、命名空间 1.为什么要有命名空间 2.定义命名空间 3.主要特点 4.使用示例 六、C输⼊&输出 …

系统架构师-面向服务架构(SOA)全解

1、为什么需要SOA架构 1.1 系统集成问题 异构系统整合 例如&#xff0c;一个企业可能同时拥有用 Java 开发的企业资源规划&#xff08;ERP&#xff09;系统、用 C# 开发的客户关系管理&#xff08;CRM&#xff09;系统以及用 Python 开发的数据分析系统。通过 SOA&#xff0…

Transformers 中的 Softmax 可以并行加速么?

Transformers 中的 Softmax 可以并行加速么&#xff1f; 面试题 Softmax 如何并行&#xff1f; Softmax 计算公式 安全的 Softmax 运算 Softmax函数在深度学习中广泛应用于多分类问题的输出层&#xff0c;它通过指数化和归一化将一个实数向量转换为概率分布。然而&#xff…

基于springboot vue 大学生竞赛管理系统设计与实现

博主介绍&#xff1a;专注于Java vue .net php phython 小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设&#xff0c;从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不然下次找不到哟 我的博客空间发布了1000毕设题目 方便大家学习使用 感兴趣的…

YoloV10改进策略:BackBone改进|PoolFormer赋能YoloV10,视觉检测性能显著提升的创新尝试

摘要 在深度学习的广阔领域中,目标检测作为计算机视觉的基石任务之一,始终吸引着研究者的广泛关注。近期,我们大胆尝试将前沿的PoolFormer主干网络引入经典的目标检测框架YoloV10中,这一创新性融合不仅为YoloV10注入了新的活力,更在检测精度与效率上实现了双重飞跃,成为…

【Linux学习】【Ubuntu入门】2-1 Linux系统下运行C语言输出hello word

1.双击打开VMware软件&#xff0c;点击开启此虚拟机后&#xff0c;等待点击头像输入密码进入 2.“CtrlAltt”调出命令行终端&#xff0c;输入命令sudo apt-get install vim安装vim&#xff0c;输入命令sudo apt-get install gcc安装gcc 3.输入命令vi hello.c进入C语言编写环境&…

Web端云剪辑解决方案,提供多轨视频、音频、特效、字幕轨道可视化编辑

传统视频剪辑软件的繁琐安装、高昂硬件要求以及跨平台协作的局限性&#xff0c;让无数创意者望而却步。美摄科技作为云端视频编辑技术的领航者&#xff0c;携其革命性的Web端云剪辑解决方案&#xff0c;正重新定义视频创作的边界&#xff0c;让专业级视频剪辑触手可及&#xff…

【Linux】Docker下载与使用-nginx

目录 一、Docker介绍 二、Docker结构 三、下载Daocker 1. 在linux上下载docker&#xff0c;执行以下命令即可&#xff1a; 2. 开启docker 3. 执行以下操作并进行使用 四、在Docker上安装nginx 一、Docker介绍 Docker&#xff1a;是给予Go语言实现的开源项…

深入探讨 Docker:远程登录与镜像管理

深入探讨 Docker&#xff1a;远程登录与镜像管理 走一路&#xff0c;寻索一路。每有胡杨树&#xff0c;我必仔细浏览&#xff0c;驻足长久&#xff0c;如急于兑现一个久远的梦。而更多平常的日子如同荒原本身一样朴实无华&#xff0c;如同岁月一样不露形色&#xff0c;只守着一…

统信服务器操作系统【SSH登录常见问题】解决方案

方案适用于统信服务器操作系统D/E/A版。 文章目录 前言问题及解决方案问题一问题现象问题原因问题方案问题二问题现象问题原因问题方案问题三问题原因问题方案问题四问题现象问题原因问题方案问题五问题现象问题原因问题方案问题六问题现象问题原因问题方案前言 介绍日常使用s…

SPI驱动学习七(SPI_Slave_Mode驱动程序框架)

目录 一、SPI_Slave_Mode驱动程序框架1. Master和Slave模式差别1.1 主设备 (Master)1.2 从设备 (Slave)1.3 示例 2. SPI传输概述2.1 数据组织方式2.2 SPI控制器数据结构 3. SPI Slave Mode数据传输过程4. 如何编写程序4.1 设备树4.2 内核相关4.3 简单的示例代码4.3.1 master和s…