1. MySQL SQL基础练习的价值与意义
对于任何想要掌握数据库操作的数据从业者来说,SQL基础练习都是必经之路。我见过太多新手在面试时被简单的JOIN操作难倒,也见过不少工作两三年的开发者在处理复杂查询时手忙脚乱。100道基础练习题的价值,就在于它能系统性地覆盖MySQL日常开发中的各个核心场景。
这些题目不是随意拼凑的,而是经过精心设计,从最简单的SELECT语句开始,逐步深入到多表关联、子查询、聚合函数等高级用法。每道题都针对特定的SQL知识点,通过实际的数据操作场景,让你在解决问题中掌握技能。比如第15题可能专门考察WHERE条件的使用技巧,第47题则聚焦GROUP BY与HAVING的配合。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 练习环境准备与数据集搭建
2.1 MySQL环境配置建议
工欲善其事,必先利其器。我推荐使用MySQL 8.0社区版作为练习环境,它不仅免费,还支持窗口函数等新特性。安装时注意以下几点:
- 设置合适的字符集(推荐utf8mb4)
- 配置合理的缓冲区大小(初学者16MB足够)
- 记住root密码并创建专用练习用户
sql复制-- 创建练习专用用户
CREATE USER 'sql_practice'@'localhost' IDENTIFIED BY 'SafePassword123!';
GRANT ALL PRIVILEGES ON *.* TO 'sql_practice'@'localhost';
FLUSH PRIVILEGES;
2.2 练习数据集设计
好的练习题需要配套的数据模型。经典的练习库通常包含:
- 学生管理系统(学生表、课程表、成绩表)
- 电商系统(用户表、商品表、订单表)
- 员工管理系统(部门表、员工表、薪资表)
这里给出一个电商模型的建表语句示例:
sql复制CREATE DATABASE practice_db;
USE practice_db;
CREATE TABLE customers (
customer_id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE,
join_date DATE DEFAULT (CURRENT_DATE)
);
CREATE TABLE products (
product_id INT PRIMARY KEY AUTO_INCREMENT,
product_name VARCHAR(100) NOT NULL,
price DECIMAL(10,2) CHECK (price > 0),
stock_quantity INT DEFAULT 0
);
CREATE TABLE orders (
order_id INT PRIMARY KEY AUTO_INCREMENT,
customer_id INT,
order_date DATETIME DEFAULT CURRENT_TIMESTAMP,
status ENUM('pending','completed','cancelled') DEFAULT 'pending',
FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
);
3. 基础查询精要解析
3.1 SELECT语句的完整执行逻辑
很多初学者以为SELECT只是简单地从表里取数据,实际上它的执行顺序大有玄机:
- FROM子句确定数据源
- WHERE条件过滤行
- GROUP BY分组
- HAVING过滤分组
- SELECT选择列
- ORDER BY排序
- LIMIT限制结果
这个顺序解释了为什么不能在WHERE中使用SELECT中定义的别名,却可以在ORDER BY中使用。
3.2 条件过滤的进阶技巧
WHERE子句远不止简单的等于比较,MySQL提供了丰富的操作符:
- BETWEEN...AND... 范围查询
- IN() 多值匹配
- LIKE 模糊查询(注意%和_的区别)
- IS NULL 空值判断
- 正则表达式REGEXP
一个综合示例:
sql复制SELECT product_name, price
FROM products
WHERE price BETWEEN 50 AND 200
AND product_name LIKE '%手机%'
AND product_id IN (SELECT product_id FROM inventory WHERE quantity > 0);
4. 多表操作实战指南
4.1 JOIN的四种核心类型
JOIN操作是SQL中最容易混淆的部分之一,必须清楚每种JOIN的区别:
- INNER JOIN:只返回两表匹配的行
- LEFT JOIN:返回左表所有行,右表不匹配则为NULL
- RIGHT JOIN:返回右表所有行,左表不匹配则为NULL
- FULL JOIN:MySQL不直接支持,需用UNION模拟
典型的多表查询示例:
sql复制SELECT c.name, o.order_id, o.order_date
FROM customers c
LEFT JOIN orders o ON c.customer_id = o.customer_id
WHERE o.status = 'completed'
ORDER BY o.order_date DESC;
4.2 子查询的优化策略
子查询虽然强大,但不当使用会导致性能问题。经验法则:
- 能用JOIN解决的尽量不用子查询
- 相关子查询(引用外部查询列)特别耗资源
- IN子查询在大数据集上性能较差
优化前:
sql复制SELECT product_name
FROM products
WHERE product_id IN (SELECT product_id FROM order_items WHERE quantity > 10);
优化后:
sql复制SELECT p.product_name
FROM products p
JOIN order_items oi ON p.product_id = oi.product_id
WHERE oi.quantity > 10;
5. 聚合函数与分组操作
5.1 GROUP BY的常见陷阱
新手在使用GROUP BY时常犯两个错误:
- SELECT列表包含非聚合列且不在GROUP BY中
- 混淆WHERE和HAVING的使用时机
正确示例:
sql复制SELECT
c.customer_id,
c.name,
COUNT(o.order_id) AS order_count,
SUM(oi.quantity * oi.unit_price) AS total_spent
FROM customers c
LEFT JOIN orders o ON c.customer_id = o.customer_id
LEFT JOIN order_items oi ON o.order_id = oi.order_id
WHERE o.status = 'completed'
GROUP BY c.customer_id, c.name
HAVING total_spent > 1000
ORDER BY total_spent DESC;
5.2 窗口函数的强大能力
MySQL 8.0引入的窗口函数极大简化了复杂分析查询:
- ROW_NUMBER():行号
- RANK():带间隔的排名
- DENSE_RANK():连续排名
- LEAD()/LAG():访问前后行数据
销售排名示例:
sql复制SELECT
product_id,
product_name,
sales_volume,
RANK() OVER (ORDER BY sales_volume DESC) AS sales_rank,
sales_volume - LAG(sales_volume) OVER (ORDER BY sales_volume DESC) AS diff_with_prev
FROM products;
6. 实战练习精选解析
6.1 经典题目1:连续登录用户
找出连续登录至少3天的用户:
sql复制SELECT DISTINCT a.user_id
FROM logins a
JOIN logins b ON a.user_id = b.user_id AND b.login_date = DATE_ADD(a.login_date, INTERVAL 1 DAY)
JOIN logins c ON a.user_id = c.user_id AND c.login_date = DATE_ADD(a.login_date, INTERVAL 2 DAY);
6.2 经典题目2:部门最高薪
查询每个部门薪资最高的员工:
sql复制SELECT d.department_name, e.employee_name, e.salary
FROM employees e
JOIN departments d ON e.department_id = d.department_id
WHERE (e.department_id, e.salary) IN (
SELECT department_id, MAX(salary)
FROM employees
GROUP BY department_id
);
7. 性能优化与最佳实践
7.1 EXPLAIN执行计划解读
分析查询性能的黄金工具:
- type列:从优到差 system > const > eq_ref > ref > range > index > ALL
- possible_keys:可能使用的索引
- key:实际使用的索引
- rows:预估检查的行数
7.2 索引使用原则
有效使用索引的注意事项:
- 为WHERE、JOIN、ORDER BY的列建索引
- 避免在索引列上使用函数
- 遵循最左前缀原则
- 区分度低的列(如性别)不适合单独建索引
错误示例:
sql复制-- 索引失效
SELECT * FROM users WHERE YEAR(create_time) = 2023;
-- 优化后
SELECT * FROM users WHERE create_time BETWEEN '2023-01-01' AND '2023-12-31';
8. 常见错误与调试技巧
8.1 语法错误排查
高频错误类型:
- 缺少逗号分隔列
- 字符串未用引号包裹
- 保留字作为标识符未转义
- 子查询返回多行但预期单行
8.2 逻辑错误调试
当查询结果不符合预期时:
- 分步执行复杂查询
- 检查JOIN条件是否完整
- 验证NULL值的处理
- 确认事务隔离级别的影响
调试技巧:
sql复制-- 临时简化查询
SELECT * FROM table1 WHERE id = 123; -- 验证基础数据
-- 逐步添加JOIN
SELECT * FROM table1 t1
JOIN table2 t2 ON t1.id = t2.t1_id -- 先验证连接是否正常
WHERE t1.id = 123;
通过这100道练习题的实战训练,你不仅能掌握MySQL的基础操作,更能深入理解SQL的执行逻辑和优化思路。记住,真正的熟练来自于反复实践和不断思考。建议每完成20题就回顾一次,总结遇到的难点和解决方案,这样的学习效果最佳。
