找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2776

积分

0

好友

386

主题
发表于 2025-12-7 22:29:33 | 查看: 53| 回复: 0

为什么需要多表查询?在规范的关系型数据库设计中,为了避免数据冗余和空间浪费,信息会被拆分到不同的表中存储。当我们需要从多张表中整合数据时,就必须通过表之间的主外键关联进行联合查询。

首先,查看数据库表结构信息,这是进行连表查询的基础。

mysql> use school;
mysql> show tables;
+------------------+
| Tables_in_school |
+------------------+
| course           |
| sc               |
| student          |
| teacher          |
+------------------+
7 rows in set (0.00 sec)

mysql> desc student;
+-------+------------------+------+-----+---------+----------------+
| Field | Type             | Null | Key | Default | Extra          |
+-------+------------------+------+-----+---------+----------------+
| sno   | int              | NO   | PRI | NULL    | auto_increment |
| sname | varchar(20)      | NO   |     | NULL    |                |
| sage  | tinyint unsigned | NO   |     | NULL    |                |
| ssex  | enum('f','m')    | NO   |     | m       |                |
+-------+------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

mysql> desc course;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| cno   | int         | NO   | PRI | NULL    |       |
| cname | varchar(20) | NO   |     | NULL    |       |
| tno   | int         | NO   |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql> desc sc;
+-------+------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------+------+-----+---------+-------+
| sno   | int  | NO   |     | NULL    |       |
| cno   | int  | NO   |     | NULL    |       |
| score | int  | NO   |     | 0       |       |
+-------+------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql> desc teacher;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| tno   | int         | NO   | PRI | NULL    |       |
| tname | varchar(20) | NO   |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
1)查询平均成绩大于60分的同学的学号和平均成绩

需求分析:
需要关联 student 表和 sc 表,获取每位学生的平均成绩并进行筛选。

表关联与数据预览:

select * from student
join sc on student.sno=sc.sno

(此处省略长结果集)

查询实现:
首先按学号分组计算平均成绩,然后使用 HAVING 子句进行过滤。

select student.sno as "学号", avg(sc.score) as "成绩平均分"
from student
join sc on student.sno=sc.sno
group by student.sno
having avg(sc.score) > 60;
2)查询所有同学的学号、姓名、选课数和总成绩

需求分析:
需要关联 studentsccourse 三张表,统计每位学生的选课数量及总分。

表关联与数据预览:

select * from student
join sc on student.sno=sc.sno
join course on sc.cno=course.cno

(此处省略长结果集)

查询实现:
按学生分组,使用 COUNTSUM 聚合函数。

select student.sno, student.sname, count(course.cno), sum(sc.score)
from student
join sc on student.sno=sc.sno
join course on sc.cno=course.cno
group by student.sno;
3)查询各科成绩最高和最低的分,以如下形式显示:课程ID、最高分、最低分

需求分析:
关联 course 表和 sc 表,按课程分组查找极值。

表关联与数据预览:

select * from course
join sc on course.cno=sc.cno;

(此处省略长结果集)

查询实现:
使用 MAXMIN 聚合函数。

select course.cno, max(sc.score), min(sc.score)
from course
join sc on course.cno=sc.cno
group by course.cno;
4)统计各位老师,所教课程的及格率

需求分析:
这是一个典型的数据分析场景,需要关联 teachercoursesc 三张表,并按老师和课程计算及格人数占比。

表关联与数据预览:

select * from teacher
join course on teacher.tno=course.tno
join sc on course.cno=sc.cno

(此处省略长结果集)

查询实现:
结合 CASE WHEN 条件判断和聚合函数进行计算。

select teacher.tname, course.cname,
concat(floor(count(case when sc.score>=60 then 1 end)/count(*)*100),"%")
from teacher
join course on teacher.tno=course.tno
join sc on course.cno=sc.cno
group by teacher.tno, course.cno;
5)查询每门课程被选修的学生数

需求分析:
关联 studentsccourse 表,按课程统计学生数量。

表关联与数据预览:
(同上例,略)

查询实现:

select course.cname, count(*)
from student
join sc on student.sno=sc.sno
join course on sc.cno=course.cno
group by course.cno;
6)查询出只选修了一门课程的全部学生的学号和姓名

需求分析:
在关联三张表后,通过分组和 HAVING 子句筛选出选课数量为1的学生。

查询实现:

select student.sno, student.sname
from student
join sc on student.sno=sc.sno
join course on sc.cno=course.cno
group by student.sno
having count(course.cno) = 1;
7)查询选修课程门数超过1门的学生信息

需求分析:
与上一题逻辑类似,改变 HAVING 中的条件即可。

查询实现:

select student.sno, student.sname
from student
join sc on student.sno=sc.sno
join course on sc.cno=course.cno
group by student.sno
having count(course.cno) > 1;
8)统计每门课程:优秀(85分以上)良好(70-85)一般(60-70)不及格(小于60)的学生列表

需求分析:
这是一个多条件分类统计问题,需要结合 CASE WHENGROUP_CONCAT 函数,将不同分数段的学生姓名合并展示。

查询实现:

select course.cname as 课程名,
group_concat(case when sc.score>85 then student.sname end) as 优秀,
group_concat(case when sc.score>=70 and sc.score<85 then student.sname end) as 良好,
group_concat(case when sc.score>=60 and sc.score<70 then student.sname end) as 一般,
group_concat(case when sc.score<60 then student.sname end) as 不及格
from student
join sc on student.sno=sc.sno
join course on sc.cno=course.cno
group by course.cno;
9)查询平均成绩大于85的所有学生的学号、姓名和平均成绩

需求分析:
关联表后分组计算平均成绩,并设置较高的筛选阈值。

查询实现:

select student.sno, student.sname, avg(sc.score)
from student
join sc on student.sno=sc.sno
join course on sc.cno=course.cno
group by student.sno
having avg(sc.score) > 85;

通过以上九个由浅入深的案例,我们系统性地演练了 JOINGROUP BYHAVING 以及 CASE WHEN 等关键SQL子句在多表查询中的综合运用。掌握这些技巧,对于处理后端开发中复杂的业务数据查询至关重要。




上一篇:MySQL权限管理详解:静态与动态权限区别及实战授权指南
下一篇:AI发展史简明指南:从规则系统到大模型的技术演进脉络
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-24 07:50 , Processed in 0.241063 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表