mysql练习题,由浅入深的 MySQL 练习题

首页 2025-10-09 13:37:59


这里为你准备了一系列由浅入深的 MySQL 练习题。它们涵盖了从基础查询到高级应用的多个方面,非常适合用来练习和巩固你的 SQL 技能。

准备工作:创建练习用的数据库和表

在开始之前,请先执行以下 SQL 脚本,创建一个名为 school 的数据库和三张表:students (学生), courses (课程), 和 scores (成绩)。
sql
-- 创建数据库
CREATE DATABASE IF NOT EXISTS school;
USE school;

-- 创建学生表
CREATE TABLE students (
    student_id INT PRIMARY KEY AUTO_INCREMENT,
    student_name VARCHAR(50) NOT NULL,
    gender ENUM('男', '女') NOT NULL,
    age INT,
    city VARCHAR(100)
);

-- 创建课程表
CREATE TABLE courses (
    course_id INT PRIMARY KEY AUTO_INCREMENT,
    course_name VARCHAR(100) NOT NULL,
    teacher_name VARCHAR(50)
);

-- 创建成绩表
CREATE TABLE scores (
    score_id INT PRIMARY KEY AUTO_INCREMENT,
    student_id INT NOT NULL,
    course_id INT NOT NULL,
    score DECIMAL(5, 2),
    -- 设置外键关联
    FOREIGN KEY (student_id) REFERENCES students(student_id),
    FOREIGN KEY (course_id) REFERENCES courses(course_id)
);

-- 插入学生数据
INSERT INTO students (student_name, gender, age, city) VALUES
('张三', '男', 20, '北京'),
('李四', '男', 22, '上海'),
('王五', '女', 21, '广州'),
('赵六', '男', 20, '北京'),
('钱七', '女', 22, '深圳'),
('孙八', '男', 23, '上海');

-- 插入课程数据
INSERT INTO courses (course_name, teacher_name) VALUES
('高等数学', '李教授'),
('线性代数', '王教授'),
('计算机基础', '张老师'),
('数据库原理', '刘老师');

-- 插入成绩数据
INSERT INTO scores (student_id, course_id, score) VALUES
(1, 1, 88.5),
(1, 3, 92.0),
(1, 4, 89.0),
(2, 1, 76.0),
(2, 2, 82.5),
(2, 4, 95.0),
(3, 1, 91.0),
(3, 2, 78.0),
(3, 3, 85.5),
(4, 1, 60.0),
(4, 3, 72.0),
(4, 4, 68.0),
(5, 2, 89.5),
(5, 3, 94.0),
(5, 4, 90.0),
(6, 1, 95.0),
(6, 2, 92.0),
(6, 3, 88.0);
 

练习题

第一部分:基础查询 (SELECT)

  1. 查询所有学生的姓名和年龄。
  2. 查询所有课程的名称和授课教师。
  3. 查询所有在北京的学生。
  4. 查询年龄大于 21 岁的学生。
  5. 查询所有姓 “张” 的学生。 (提示:使用 LIKE 和 %)
  6. 查询成绩在 80 到 90 分之间的所有记录。 (提示:使用 BETWEEN ... AND ...)
  7. 查询所有课程的名称,并去除重复的课程名。 (提示:使用 DISTINCT)

第二部分:排序和限制 (ORDER BY, LIMIT)

  1. 查询所有学生的姓名和年龄,并按年龄从大到小排序。
  2. 查询所有学生的姓名和城市,并按城市升序、姓名降序排序。
  3. 查询成绩最高的 3 条记录。

第三部分:聚合函数和分组 (GROUP BY, HAVING)

  1. 计算学生总人数。 (提示:使用 COUNT())
  2. 计算 “高等数学” 这门课的平均成绩、最高分和最低分。 (提示:使用 AVG()MAX()MIN())
  3. 查询每个学生的总分和平均分。 (提示:按 student_id 分组)
  4. 查询总分大于 250 分的学生。 (提示:使用 HAVING 子句)
  5. 查询有 3 个或 3 个以上学生选修的课程及其学生人数。

第四部分:多表连接 (JOIN)

  1. 查询每个学生的姓名及其选修的课程名称。 (提示:连接 studentsscorescourses 三张表)
  2. 查询 “张三” 同学的所有成绩记录,包括课程名和分数。
  3. 查询所有学生的姓名以及他们 “数据库原理” 这门课的成绩。如果学生没有选修这门课,成绩显示为 NULL。 (提示:使用 LEFT JOIN)
  4. 查询没有任何成绩记录的学生。 (提示:可以使用 LEFT JOIN 后判断成绩为 NULL,或使用 NOT IN)
  5. 查询每门课程的课程名和选课人数。

第五部分:子查询和高级应用

  1. 查询 “高等数学” 成绩最高的学生姓名和分数。 (提示:可以使用子查询先找出最高分)
  2. 查询所有成绩都高于 80 分的学生姓名。 (提示:可以用 NOT EXISTS 或 GROUP BY ... HAVING MIN(score) > 80)
  3. 查询与 “张三” 同龄的学生。
  4. 查询选修了 “数据库原理” 但没有选修 “计算机基础” 的学生。 (提示:使用 NOT IN 或 NOT EXISTS)
  5. 查询每门课程的前两名学生及其成绩。 (这是一个经典的 Top-N 问题,有一定难度,可以使用窗口函数或关联子查询)

答案与解析

注意: 强烈建议你先自己尝试解答,然后再对照答案。
<details><summary>点击展开查看答案</summary>

第一部分:基础查询 (SELECT)

  1. SELECT student_name, age FROM students;
  2. SELECT course_name, teacher_name FROM courses;
  3. SELECT * FROM students WHERE city = '北京';
  4. SELECT * FROM students WHERE age > 21;
  5. SELECT * FROM students WHERE student_name LIKE '张%';
  6. SELECT * FROM scores WHERE score BETWEEN 80 AND 90;
  7. SELECT DISTINCT course_name FROM courses;

第二部分:排序和限制

  1. SELECT student_name, age FROM students ORDER BY age DESC;
  2. SELECT student_name, city FROM students ORDER BY city ASC, student_name DESC;
  3. SELECT * FROM scores ORDER BY score DESC LIMIT 3;

第三部分:聚合函数和分组

  1. SELECT COUNT(*) AS total_students FROM students;
  2. SELECT AVG(score) AS avg_score, MAX(score) AS max_score, MIN(score) AS min_score FROM scores WHERE course_id = (SELECT course_id FROM courses WHERE course_name = '高等数学');
  3. SELECT s.student_id, s.student_name, SUM(sc.score) AS total_score, AVG(sc.score) AS avg_score FROM students s JOIN scores sc ON s.student_id = sc.student_id GROUP BY s.student_id, s.student_name;
  4. SELECT s.student_id, s.student_name, SUM(sc.score) AS total_score FROM students s JOIN scores sc ON s.student_id = sc.student_id GROUP BY s.student_id, s.student_name HAVING SUM(sc.score) > 250;
  5. SELECT c.course_id, c.course_name, COUNT(sc.student_id) AS student_count FROM courses c JOIN scores sc ON c.course_id = sc.course_id GROUP BY c.course_id, c.course_name HAVING COUNT(sc.student_id) >= 3;

第四部分:多表连接

  1. SELECT s.student_name, c.course_name FROM students s JOIN scores sc ON s.student_id = sc.student_id JOIN courses c ON sc.course_id = c.course_id;
  2. SELECT s.student_name, c.course_name, sc.score FROM students s JOIN scores sc ON s.student_id = sc.student_id JOIN courses c ON sc.course_id = c.course_id WHERE s.student_name = '张三';
  3. SELECT s.student_name, c.course_name, sc.score FROM students s LEFT JOIN scores sc ON s.student_id = sc.student_id AND sc.course_id = (SELECT course_id FROM courses WHERE course_name = '数据库原理') LEFT JOIN courses c ON sc.course_id = c.course_id;
  4. SELECT s.student_name FROM students s LEFT JOIN scores sc ON s.student_id = sc.student_id WHERE sc.score_id IS NULL;
  5. SELECT c.course_name, COUNT(sc.student_id) AS student_count FROM courses c LEFT JOIN scores sc ON c.course_id = sc.course_id GROUP BY c.course_id, c.course_name;

第五部分:子查询和高级应用

  1. SELECT s.student_name, sc.score FROM students s JOIN scores sc ON s.student_id = sc.student_id WHERE sc.course_id = (SELECT course_id FROM courses WHERE course_name = '高等数学') AND sc.score = (SELECT MAX(score) FROM scores WHERE course_id = (SELECT course_id FROM courses WHERE course_name = '高等数学'));
  2. SELECT s.student_name FROM students s WHERE NOT EXISTS (SELECT 1 FROM scores sc WHERE sc.student_id = s.student_id AND sc.score <= 80);
  3. SELECT student_name FROM students WHERE age = (SELECT age FROM students WHERE student_name = '张三') AND student_name != '张三';
  4. SELECT s.student_name FROM students s WHERE s.student_id IN (SELECT student_id FROM scores WHERE course_id = (SELECT course_id FROM courses WHERE course_name = '数据库原理')) AND s.student_id NOT IN (SELECT student_id FROM scores WHERE course_id = (SELECT course_id FROM courses WHERE course_name = '计算机基础'));
  5. 使用窗口函数 (MySQL 8.0+) (推荐):
    sql
    SELECT student_name, course_name, score
    FROM (
        SELECT
            s.student_name,
            c.course_name,
            sc.score,
            ROW_NUMBER() OVER(PARTITION BY sc.course_id ORDER BY sc.score DESC) as rn
        FROM scores sc
        JOIN students s ON sc.student_id = s.student_id
        JOIN courses c ON sc.course_id = c.course_id
    ) t
    WHERE rn <= 2
    ORDER BY course_name, score DESC;
    
     
     
</details>
祝你练习顺利!这些题目覆盖了大部分常用的 SQL 场景,掌握它们将对你的数据库操作能力有很大提升。
 
 

MySQL连接就这么简单!本地远程、编程语言连接方法一网打尽
还在为MySQL日期计算头疼?这份加一天操作指南能解决90%问题
MySQL日志到底在哪里?Linux/Windows/macOS全平台查找方法在此
MySQL数据库管理工具全景评测:从Workbench到DBeaver的技术选型指南
MySQL密码忘了怎么办?这份重置指南能救急,Windows/Linux/Mac都适用
你的MySQL为什么经常卡死?可能是锁表在作怪!快速排查方法在此
MySQL单表卡爆怎么办?从策略到实战,一文掌握「分表」救命技巧
清空MySQL数据表千万别用错!DELETE和TRUNCATE这个区别可能导致重大事故
你的MySQL中文排序一团糟?记住这几点,轻松实现准确拼音排序!
别再混淆Hive和MySQL了!读懂它们的天壤之别,才算摸到大数据的门道