一、表结构设计
1.数据库及表结构设计
sql
-- 创建数据库
CREATE DATABASE IF NOT EXISTS school_db;
USE school_db;
-- 学生表(存储学生基本信息)
CREATE TABLE IF NOT EXISTS students
(
student_id INT PRIMARY KEY COMMENT '学号(主键)',
name VARCHAR(50) NOT NULL COMMENT '姓名',
gender CHAR(1) COMMENT '性别(男/女)',
age INT COMMENT '年龄',
class VARCHAR(20) COMMENT '班级'
);
-- 教师表(存储教师基本信息)
CREATE TABLE IF NOT EXISTS teachers
(
teacher_id INT PRIMARY KEY COMMENT '教师号(主键)',
name VARCHAR(50) NOT NULL COMMENT '姓名',
gender CHAR(1) COMMENT '性别(男/女)',
department VARCHAR(50) COMMENT '所属部门'
);
-- 课程表(存储课程信息,关联教师)
CREATE TABLE IF NOT EXISTS courses
(
course_id INT PRIMARY KEY COMMENT '课程号(主键)',
course_name VARCHAR(100) NOT NULL COMMENT '课程名',
credits DECIMAL(2, 1) COMMENT '学分',
teacher_id INT COMMENT '授课教师号(外键)',
FOREIGN KEY (teacher_id) REFERENCES teachers (teacher_id)
);
-- 选课表(存储学生选课及成绩,关联学生和课程)
CREATE TABLE IF NOT EXISTS enrollments
(
student_id INT COMMENT '学号(外键)',
course_id INT COMMENT '课程号(外键)',
score DECIMAL(5, 2) COMMENT '成绩',
enroll_date DATE COMMENT '选课日期',
PRIMARY KEY (student_id, course_id), -- 联合主键(一个学生一门课只选一次)
FOREIGN KEY (student_id) REFERENCES students (student_id),
FOREIGN KEY (course_id) REFERENCES courses (course_id)
);
2.插入测试数据
sql
-- 插入学生数据
INSERT INTO students (student_id, name, gender, age, class)
VALUES (1, '张三', '男', 19, '高一(1)班'),
(2, '李四', '女', 18, '高一(1)班'),
(3, '王五', '男', 17, '高一(2)班'),
(4, '赵六', '女', 19, '高一(2)班'),
(5, '孙七', '男', 18, '高一(3)班'),
(6, '周八', '女', 17, '高一(3)班'),
(7, '吴九', '男', 19, '高一(1)班'),
(8, '郑十', '女', 18, '高一(2)班');
-- 插入教师数据
INSERT INTO teachers (teacher_id, name, gender, department)
VALUES (101, '王老师', '女', '数学组'),
(102, '李老师', '男', '语文组'),
(103, '张老师', '男', '英语组'),
(104, '刘老师', '女', '物理组');
-- 插入课程数据
INSERT INTO courses (course_id, course_name, credits, teacher_id)
VALUES (1001, '数学', 3.0, 101),
(1002, '语文', 2.5, 102),
(1003, '英语', 3.0, 103),
(1004, '物理', 2.0, 104),
(1005, '化学', 2.0, 104);
-- 刘老师同时教物理和化学
-- 插入选课数据
INSERT INTO enrollments (student_id, course_id, score, enroll_date)
VALUES (1, 1001, 90.5, '2023-09-01'),
(1, 1002, 85.0, '2023-09-01'),
(1, 1003, 88.5, '2023-09-01'),
(2, 1001, 82.0, '2023-09-01'),
(2, 1002, 92.5, '2023-09-01'),
(3, 1001, 76.0, '2023-09-01'),
(3, 1003, 95.0, '2023-09-01'),
(3, 1004, 80.5, '2023-09-01'),
(4, 1002, 78.0, '2023-09-01'),
(4, 1004, 89.0, '2023-09-01'),
(5, 1001, 85.5, '2023-09-01'),
(5, 1005, 91.0, '2023-09-01'),
(6, 1003, 79.5, '2023-09-01'),
(6, 1005, 86.0, '2023-09-01'),
(7, 1001, 68.0, '2023-09-01'),
(7, 1004, 72.5, '2023-09-01'),
(8, 1002, 88.0, '2023-09-01'),
(8, 1003, 93.0, '2023-09-01');
二、习题及答案
1.基础查询
sql
-- 1.查询所有学生的姓名和年龄
SELECT name, age
FROM students;
-- 2.查询高一 (1) 班的所有学生信息
SELECT *
FROM students
WHERE class = '高一(1)班';
-- 3.查询年龄大于 18 岁的男生姓名和班级
SELECT name, class
FROM students
WHERE age > 18
AND gender = '男';
-- 4.查询所有课程的名称和学分
SELECT course_name, credits
FROM courses;
-- 5.查询学分大于等于 3.0 的课程名称
SELECT course_name
FROM courses
WHERE credits >= 3.0;
-- 6.查询教师表中所有女教师的姓名和部门
SELECT name, department
FROM teachers
WHERE gender = '女';
-- 7.查询选课表中成绩在 80-90 分(含 80 和 90)的记录
SELECT *
FROM enrollments
WHERE score BETWEEN 80 AND 90;
-- 8.查询姓名以 "张" 开头的学生信息
SELECT *
FROM students
WHERE name LIKE '张%';
-- 9.查询班级包含 "(1)" 的学生姓名
SELECT name
FROM students
WHERE class LIKE '%(1)%';
-- 10.查询所有学生的学号、姓名,并按年龄从大到小排序
SELECT student_id, name
FROM students
ORDER BY age DESC;
2.多表连接查询
sql
-- 11.查询每个学生的姓名及所选课程名称
SELECT s.name, c.course_name
FROM students s
JOIN enrollments e ON s.student_id = e.student_id
JOIN courses c ON e.course_id = c.course_id;
-- 12.查询 "数学" 课程的所有选课学生姓名和成绩
SELECT s.name, e.score
FROM students s
JOIN enrollments e ON s.student_id = e.student_id
JOIN courses c ON e.course_id = c.course_id
WHERE c.course_name = '数学';
-- 13.查询 "王老师" 教的所有课程名称
SELECT c.course_name
FROM courses c
JOIN teachers t ON c.teacher_id = t.teacher_id
WHERE t.name = '王老师';
-- 14.查询每个学生的姓名、班级及所选课程的学分
SELECT s.name, s.class, c.credits
FROM students s
JOIN enrollments e ON s.student_id = e.student_id
JOIN courses c ON e.course_id = c.course_id;
-- 15.查询 "高一 (2) 班" 学生所选的课程名称及授课教师姓名
SELECT c.course_name, t.name
FROM students s
JOIN enrollments e ON s.student_id = e.student_id
JOIN courses c ON e.course_id = c.course_id
JOIN teachers t ON c.teacher_id = t.teacher_id
WHERE s.class = '高一(2)班';
-- 16.查询所有学生的姓名及他们的选课日期(包括未选课的学生)
SELECT s.name, e.enroll_date
FROM students s
LEFT JOIN enrollments e ON s.student_id = e.student_id;
-- 17.查询没有学生选的课程名称
SELECT c.course_name
FROM courses c
LEFT JOIN enrollments e ON c.course_id = e.course_id
WHERE e.student_id IS NULL;
-- 18.查询 "英语" 课程成绩最高的学生姓名和成绩
SELECT s.name, e.score
FROM students s
JOIN enrollments e ON s.student_id = e.student_id
JOIN courses c ON e.course_id = c.course_id
WHERE c.course_name = '英语'
ORDER BY e.score DESC
LIMIT 1;
-- 19.查询 "李老师" 教的课程中,成绩大于 85 分的学生姓名
SELECT s.name
FROM students s
JOIN enrollments e ON s.student_id = e.student_id
JOIN courses c ON e.course_id = c.course_id
JOIN teachers t ON c.teacher_id = t.teacher_id
WHERE t.name = '李老师'
AND e.score > 85;
-- 20查询每个学生的姓名和所选课程的总分(按总分从高到低排序)
SELECT s.name, SUM(e.score) AS total_score
FROM students s
JOIN enrollments e ON s.student_id = e.student_id
GROUP BY s.student_id, s.name
ORDER BY total_score DESC;
3.聚合与分组查询
sql
-- 21.统计每个班级的学生人数
SELECT class, COUNT(*) AS student_count
FROM students
GROUP BY class;
-- 22.计算每门课程的平均成绩
SELECT c.course_name, AVG(e.score) AS avg_score
FROM courses c
JOIN enrollments e ON c.course_id = e.course_id
GROUP BY c.course_id, c.course_name;
-- 23.统计每个教师所教课程的总学分
SELECT t.name, SUM(c.credits) AS total_credits
FROM teachers t
JOIN courses c ON t.teacher_id = c.teacher_id
GROUP BY t.teacher_id, t.name;
-- 24.查询选课人数大于 3 人的课程名称和选课人数
SELECT c.course_name, COUNT(e.student_id) AS enroll_count
FROM courses c
JOIN enrollments e ON c.course_id = e.course_id
GROUP BY c.course_id, c.course_name
HAVING enroll_count > 3;
-- 25.计算每个学生的选课门数
SELECT s.name, COUNT(e.course_id) AS course_count
FROM students s
JOIN enrollments e ON s.student_id = e.student_id
GROUP BY s.student_id, s.name;
-- 26.查询平均成绩大于 85 分的课程名称和平均成绩
SELECT c.course_name, AVG(e.score) AS avg_score
FROM courses c
JOIN enrollments e ON c.course_id = e.course_id
GROUP BY c.course_id, c.course_name
HAVING avg_score > 85;
-- 27.统计每个性别的学生人数
SELECT gender, COUNT(*) AS count
FROM students
GROUP BY gender;
-- 28.查询 "高一 (1) 班" 学生的平均年龄
SELECT AVG(age) AS avg_age
FROM students
WHERE class = '高一(1)班';
-- 29.计算每门课程的最高分和最低分
SELECT c.course_name, MAX(e.score) AS max_score, MIN(e.score) AS min_score
FROM courses c
JOIN enrollments e ON c.course_id = e.course_id
GROUP BY c.course_id, c.course_name;
-- 30.统计每个部门的教师人数
SELECT department, COUNT(*) AS teacher_count
FROM teachers
GROUP BY department;
4.子查询
sql
-- 31.查询与 "张三" 同班的学生姓名
SELECT name
FROM students
WHERE class = (SELECT class FROM students WHERE name = '张三')
AND name != '张三';
-- 32.查询成绩高于 "数学" 课程平均成绩的学生姓名和成绩
SELECT s.name, e.score
FROM students s
JOIN enrollments e ON s.student_id = e.student_id
WHERE e.course_id = (SELECT course_id FROM courses WHERE course_name = '数学')
AND e.score >
(SELECT AVG(score) FROM enrollments WHERE course_id = (SELECT course_id FROM courses WHERE course_name = '数学'));
-- 33.查询选修了 "物理" 课程的学生所在的班级
SELECT DISTINCT class
FROM students
WHERE student_id IN
(SELECT student_id FROM enrollments WHERE course_id = (SELECT course_id FROM courses WHERE course_name = '物理'));
-- 34.查询没有选修 "语文" 课程的学生姓名
SELECT name
FROM students
WHERE student_id NOT IN
(SELECT student_id FROM enrollments WHERE course_id = (SELECT course_id FROM courses WHERE course_name = '语文'));
-- 35.查询比 "高一 (1) 班" 所有学生年龄都小的学生姓名和年龄
SELECT name, age
FROM students
WHERE age < ALL (SELECT age FROM students WHERE class = '高一(1)班');
-- 36.查询至少选修了 "张三" 所选课程中一门的学生姓名
SELECT DISTINCT s.name
FROM students s
JOIN enrollments e ON s.student_id = e.student_id
WHERE e.course_id IN
(SELECT course_id FROM enrollments WHERE student_id = (SELECT student_id FROM students WHERE name = '张三'))
AND s.name != '张三';
-- 37.查询 "英语" 成绩最高的学生姓名
SELECT name
FROM students
WHERE student_id = (SELECT student_id
FROM enrollments
WHERE course_id = (SELECT course_id FROM courses WHERE course_name = '英语')
AND score = (SELECT MAX(score)
FROM enrollments
WHERE course_id = (SELECT course_id FROM courses WHERE course_name = '英语')));
-- 38.查询教了 3 学分课程的教师姓名
SELECT name
FROM teachers
WHERE teacher_id IN (SELECT teacher_id FROM courses WHERE credits = 3.0);
-- 39.查询成绩不及格(<60 分)的学生姓名(若有)
SELECT s.name
FROM students s
JOIN enrollments e ON s.student_id = e.student_id
WHERE e.score < 60;
-- 40查询选课门数超过 2 门的学生姓名
SELECT name
FROM students
WHERE student_id IN (SELECT student_id FROM enrollments GROUP BY student_id HAVING COUNT(course_id) > 2);
5.增删改操作
sql
-- 41.新增一个学生:学号 9,姓名 "钱十一",女,17 岁,班级 "高一 (3) 班"
INSERT INTO students (student_id, name, gender, age, class)
VALUES (9, '钱十一', '女', 17, '高一(3)班');
-- 42.新增一门课程:课程号 1006,名称 "生物",学分 2.5,授课教师为 "张老师"
INSERT INTO courses (course_id, course_name, credits, teacher_id)
VALUES (1006, '生物', 2.5, (SELECT teacher_id FROM teachers WHERE name = '张老师'));
-- 43.为 "钱十一" 添加选课记录:选修 "生物",成绩 82 分,选课日期 2023-09-02
INSERT INTO enrollments (student_id, course_id, score, enroll_date)
VALUES (9, 1006, 82.0, '2023-09-02');
-- 44.将 "张三" 的年龄修改为 20 岁
UPDATE students
SET age = 20
WHERE name = '张三';
-- 45.将 "数学" 课程的学分修改为 3.5
UPDATE courses
SET credits = 3.5
WHERE course_name = '数学';
-- 46.将 "李四" 的 "语文" 成绩提高 5 分(原成绩 82.0→87.0)
UPDATE enrollments
SET score = score + 5
WHERE student_id = (SELECT student_id FROM students WHERE name = '李四')
AND course_id = (SELECT course_id FROM courses WHERE course_name = '语文');
-- 47.删除 "郑十" 的 "英语" 选课记录
DELETE
FROM enrollments
WHERE student_id = (SELECT student_id FROM students WHERE name = '郑十')
AND course_id = (SELECT course_id FROM courses WHERE course_name = '英语');
-- 48.删除 "化学" 课程的所有选课记录
DELETE
FROM enrollments
WHERE course_id = (SELECT course_id FROM courses WHERE course_name = '化学');
-- 49.删除学号为 7 的学生信息(需先删除其选课记录,否则外键约束报错)
DELETE
FROM enrollments
WHERE student_id = 7;
DELETE
FROM students
WHERE student_id = 7;
-- 50将 "物理组" 所有教师的性别修改为 "女"
UPDATE teachers
SET gender = '女'
WHERE department = '物理组';