1. MySQL SQL 基础练习的价值与意义
对于任何想要掌握数据库操作的数据从业者来说,SQL 基础练习都是必不可少的环节。我见过太多新手在面试时因为基础 SQL 不熟练而错失机会,也见过不少工作两三年的开发因为 SQL 基础薄弱导致系统性能问题。MySQL 作为最流行的开源关系型数据库,其 SQL 语法是行业标准的基础。
这 100 道练习题覆盖了从最简单的 SELECT 查询到复杂的多表连接、子查询等核心知识点。通过系统性地完成这些练习,你能够:
- 建立完整的 SQL 语法体系框架
- 掌握实际业务场景中的查询技巧
- 避免常见的 SQL 编写误区
- 为后续学习高级优化技巧打下坚实基础
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 练习环境准备与数据集构建
2.1 MySQL 安装与配置
建议使用 MySQL 8.0 版本进行练习,这是目前最稳定的生产版本。安装过程非常简单:
bash复制# Ubuntu/Debian
sudo apt update
sudo apt install mysql-server
# CentOS/RHEL
sudo yum install mysql-server
# macOS (使用Homebrew)
brew install mysql
安装完成后,启动服务并设置 root 密码:
bash复制sudo systemctl start mysql
sudo mysql_secure_installation
提示:练习时可以为每个专题创建单独的数据库用户,避免使用 root 账户操作
2.2 练习数据集设计
我们设计了一个典型的学生选课系统模型,包含以下表结构:
sql复制-- 创建数据库
CREATE DATABASE school;
USE school;
-- 学生表
CREATE TABLE students (
student_id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
gender ENUM('M','F'),
birth_date DATE,
enrollment_date DATE,
major VARCHAR(50)
);
-- 课程表
CREATE TABLE courses (
course_id INT PRIMARY KEY,
course_name VARCHAR(100) NOT NULL,
credit FLOAT,
department VARCHAR(50)
);
-- 教师表
CREATE TABLE teachers (
teacher_id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
title VARCHAR(20),
department VARCHAR(50)
);
-- 选课记录表
CREATE TABLE enrollments (
enrollment_id INT PRIMARY KEY,
student_id INT,
course_id INT,
teacher_id INT,
semester VARCHAR(20),
score FLOAT,
FOREIGN KEY (student_id) REFERENCES students(student_id),
FOREIGN KEY (course_id) REFERENCES courses(course_id),
FOREIGN KEY (teacher_id) REFERENCES teachers(teacher_id)
);
3. 基础查询练习(1-30题)
3.1 单表查询基础
sql复制-- 1. 查询所有学生信息
SELECT * FROM students;
-- 2. 查询学生姓名和专业
SELECT name, major FROM students;
-- 3. 查询不同专业列表(去重)
SELECT DISTINCT major FROM students;
-- 4. 查询1995年后出生的学生
SELECT * FROM students WHERE birth_date > '1995-01-01';
-- 5. 查询计算机专业且为男性的学生
SELECT * FROM students
WHERE major = 'Computer Science' AND gender = 'M';
3.2 排序与分页
sql复制-- 6. 按入学日期降序排列学生
SELECT * FROM students ORDER BY enrollment_date DESC;
-- 7. 按专业升序,同专业按姓名排序
SELECT * FROM students ORDER BY major, name;
-- 8. 分页查询学生(每页10条,第2页)
SELECT * FROM students LIMIT 10 OFFSET 10;
3.3 聚合函数应用
sql复制-- 9. 统计学生总数
SELECT COUNT(*) FROM students;
-- 10. 统计各专业学生人数
SELECT major, COUNT(*) FROM students GROUP BY major;
-- 11. 查询平均学分最高的前3个专业
SELECT major, AVG(credit) as avg_credit
FROM students GROUP BY major ORDER BY avg_credit DESC LIMIT 3;
4. 多表连接与子查询(31-70题)
4.1 内连接与左连接
sql复制-- 31. 查询学生及其选课信息
SELECT s.name, e.course_id, e.score
FROM students s
JOIN enrollments e ON s.student_id = e.student_id;
-- 32. 查询所有课程及选课学生(包括无人选的课程)
SELECT c.course_name, s.name
FROM courses c
LEFT JOIN enrollments e ON c.course_id = e.course_id
LEFT JOIN students s ON e.student_id = s.student_id;
4.2 复杂子查询
sql复制-- 45. 查询成绩高于平均分的学生
SELECT s.name, e.score
FROM students s
JOIN enrollments e ON s.student_id = e.student_id
WHERE e.score > (SELECT AVG(score) FROM enrollments);
-- 46. 查询选了"数据库原理"课程的学生
SELECT s.name
FROM students s
WHERE s.student_id IN (
SELECT e.student_id
FROM enrollments e
JOIN courses c ON e.course_id = c.course_id
WHERE c.course_name = 'Database Principles'
);
4.3 多表联合查询
sql复制-- 60. 查询每门课程的授课教师和学生人数
SELECT
c.course_name,
t.name AS teacher_name,
COUNT(e.student_id) AS student_count
FROM courses c
JOIN enrollments e ON c.course_id = e.course_id
JOIN teachers t ON e.teacher_id = t.teacher_id
GROUP BY c.course_name, t.name;
5. 高级功能与优化技巧(71-100题)
5.1 窗口函数应用
sql复制-- 71. 查询每门课程成绩排名
SELECT
c.course_name,
s.name,
e.score,
RANK() OVER (PARTITION BY e.course_id ORDER BY e.score DESC) AS rank
FROM enrollments e
JOIN students s ON e.student_id = s.student_id
JOIN courses c ON e.course_id = c.course_id;
5.2 事务与锁机制
sql复制-- 85. 事务处理示例:学生转专业
START TRANSACTION;
UPDATE students
SET major = 'Data Science'
WHERE student_id = 1001;
UPDATE enrollments
SET teacher_id = 2005
WHERE student_id = 1001 AND semester = '2023-Fall';
COMMIT;
5.3 性能优化实践
sql复制-- 92. 为常用查询添加索引
ALTER TABLE enrollments ADD INDEX idx_student_course (student_id, course_id);
-- 93. 使用EXPLAIN分析查询
EXPLAIN SELECT * FROM students WHERE major = 'Computer Science';
-- 94. 避免全表扫描的查询优化
-- 不推荐
SELECT * FROM students WHERE YEAR(birth_date) = 1995;
-- 推荐
SELECT * FROM students
WHERE birth_date BETWEEN '1995-01-01' AND '1995-12-31';
6. 常见问题与解决方案
6.1 语法错误排查
问题1: GROUP BY 与 SELECT 列不匹配
sql复制-- 错误示例
SELECT name, major, COUNT(*)
FROM students
GROUP BY major;
-- 正确写法
SELECT major, COUNT(*)
FROM students
GROUP BY major;
问题2: 多表连接时的列歧义
sql复制-- 错误示例
SELECT name FROM students, enrollments
WHERE student_id = student_id;
-- 正确写法
SELECT s.name FROM students s, enrollments e
WHERE s.student_id = e.student_id;
6.2 性能问题优化
问题: 大数据量查询缓慢
- 解决方案:
- 添加适当的索引
- 限制返回的列数
- 使用分页查询
- 避免在 WHERE 子句中对字段进行函数操作
6.3 实际应用技巧
- 命名规范:表名使用复数形式,列名使用下划线分隔
- 注释习惯:复杂SQL添加注释说明业务逻辑
- 版本控制:将重要SQL脚本纳入版本管理
- 安全注意:永远不要拼接SQL语句,使用参数化查询
7. 练习进阶建议
完成这100道基础练习后,可以尝试以下进阶方向:
- 复杂业务场景模拟:设计电商、社交网络等业务模型
- 性能优化专项:学习执行计划分析、索引优化策略
- 存储过程与触发器:掌握数据库编程能力
- 不同数据库方言:比较MySQL、PostgreSQL、Oracle等差异
我在实际工作中发现,很多开发人员对SQL的理解停留在表面。真正深入掌握SQL需要不断练习和思考,特别是要理解每个查询背后的执行逻辑。建议每完成一个专题后,尝试用EXPLAIN分析查询计划,这对理解数据库工作原理非常有帮助。
