LeetCode MySQL刷题指南:从入门到精通

发布时间:2026/10/28 7:35:54
LeetCode MySQL刷题指南:从入门到精通

1. 为什么选择LeetCode刷MySQL题?

作为一名数据库工程师,我最初接触LeetCode的MySQL题库纯粹是为了应付面试。但真正坚持刷了三个月后,发现这套题库的价值远超预期——它系统性地覆盖了SQL语言90%以上的核心知识点,特别是那些实际工作中容易忽略的边界场景。

LeetCode的MySQL题库目前有约150道题目,按难度分为简单、中等和困难三个级别。与其他刷题平台相比,它的特色在于:

  • 每道题都提供真实的数据表结构和测试用例
  • 支持在线编写SQL并即时验证结果
  • 题目描述模拟了真实业务场景的需求
  • 讨论区有大量优质解法可以参考

提示:建议从「简单」难度开始建立信心,但不要长期停留在舒适区。我个人的经验是,连续刷20道简单题后就应该挑战中等难度。

2. 刷题前的环境准备

2.1 本地MySQL环境配置

虽然LeetCode提供在线执行环境,但本地搭建MySQL环境能让你更自由地测试各种写法。推荐使用Docker快速部署:

docker run --name leetcode-mysql -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 -d mysql:8.0

安装完成后,建议配置:

  1. 设置SQL模式为严格模式(避免宽松模式下的隐式转换)
SET GLOBAL sql_mode = 'STRICT_TRANS_TABLES';
  1. 创建专用数据库
CREATE DATABASE leetcode CHARACTER SET utf8mb4;

2.2 数据导入技巧

LeetCode每道题都会给出类似这样的表结构:

CREATE TABLE Employees ( id INT PRIMARY KEY, name VARCHAR(50), department VARCHAR(50), salary INT );

我开发了一个Python脚本自动生成测试数据(完整代码见附录):

  • 根据字段类型生成合理值
  • 确保外键关联正确
  • 制造边界条件数据(如NULL值)

3. 核心解题方法论

3.1 四步分析法

面对任何SQL题目,我都遵循以下步骤:

  1. 需求拆解:用红笔圈出题目中的关键条件

    • 示例:找出"薪资高于部门平均值"的员工
    • 隐含需求:需要先计算每个部门的平均薪资
  2. 表关系分析:绘制ER图理清连接关系

    • 自连接的特殊处理
    • 多表连接的顺序选择
  3. 执行计划预判:EXPLAIN分析可能的性能瓶颈

    • 重点关注type列(最好到range级别)
    • 注意Using filesort和Using temporary
  4. 边界测试:验证极端情况

    • NULL值处理
    • 空表情况
    • 重复数据

3.2 高频考点精讲

3.2.1 窗口函数实战

窗口函数是中等难度以上的必考内容。以经典题目「部门工资前三高的员工」为例:

SELECT Department, Employee, Salary FROM ( SELECT d.name AS Department, e.name AS Employee, e.salary AS Salary, DENSE_RANK() OVER (PARTITION BY e.departmentId ORDER BY e.salary DESC) AS rnk FROM Employee e JOIN Department d ON e.departmentId = d.id ) t WHERE rnk <= 3;

注意:区分RANK()、DENSE_RANK()和ROW_NUMBER()的使用场景:

  • RANK():并列排名会跳过后续序号(1,2,2,4)
  • DENSE_RANK():并列排名不跳号(1,2,2,3)
  • ROW_NUMBER():强制连续编号(1,2,3,4)
3.2.2 递归CTE应用

处理树形结构数据时,递归CTE是终极武器。比如「员工层级关系查询」:

WITH RECURSIVE EmpHierarchy AS ( -- 基础查询:找出CEO SELECT id, name, managerId, 1 AS level FROM Employee WHERE managerId IS NULL UNION ALL -- 递归查询:逐级向下查找 SELECT e.id, e.name, e.managerId, eh.level + 1 FROM Employee e JOIN EmpHierarchy eh ON e.managerId = eh.id ) SELECT * FROM EmpHierarchy;

4. 性能优化进阶

4.1 索引设计原则

根据题目特点创建合适的索引:

  • 高频过滤条件列建单列索引
  • 多列条件考虑组合索引
  • 注意最左前缀原则
-- 题目:频繁按部门和薪资范围查询 ALTER TABLE Employees ADD INDEX idx_dept_salary (department, salary);

4.2 执行计划深度解析

以「查找没有订单的客户」为例,对比两种写法:

写法A:NOT IN

EXPLAIN SELECT name FROM Customers WHERE id NOT IN (SELECT customerId FROM Orders);

写法B:LEFT JOIN

EXPLAIN SELECT c.name FROM Customers c LEFT JOIN Orders o ON c.id = o.customerId WHERE o.id IS NULL;

执行计划关键指标对比:

指标NOT INLEFT JOIN
typeALLeq_ref
rows全表扫描索引查找
ExtraUsing whereUsing where; Not exists

5. 错题本管理技巧

我维护的错题本包含以下维度:

  1. 题目分类

    • 连接查询
    • 子查询
    • 聚合函数
    • 日期处理
    • 字符串处理
  2. 错误原因

    • 语法错误(30%)
    • 逻辑错误(50%)
    • 性能问题(20%)
  3. 改进方案

    • 重写SQL
    • 添加索引
    • 修改表结构

示例记录:

题目:第N高的薪水 错误:忽略了NULL处理 修正:使用IFNULL包装结果

6. 刷题路线建议

根据三个月刷完所有题目的经验,推荐如下节奏:

阶段目标时间重点
入门简单题50道2周基础语法
进阶中等题80道4周复杂查询
攻坚困难题20道2周性能优化
复习错题重做持续查漏补缺

每日建议:

  • 新题3道(含至少1道中等)
  • 复习错题5道
  • 每周总结一次知识图谱

7. 实战案例解析

7.1 连续登录问题

题目:查找连续登录至少5天的用户

解决方案:

SELECT DISTINCT a.user_id FROM Logins a JOIN Logins b ON a.user_id = b.user_id AND DATEDIFF(b.login_date, a.login_date) BETWEEN 1 AND 4 GROUP BY a.user_id, a.login_date HAVING COUNT(DISTINCT b.login_date) = 4;

优化思路:

  1. 在user_id和login_date上创建组合索引
  2. 使用窗口函数替代自连接(MySQL 8.0+)

7.2 留存率计算

题目:计算次日留存率

SELECT ROUND( COUNT(DISTINCT b.user_id) / COUNT(DISTINCT a.user_id), 2 ) AS retention_rate FROM (SELECT DISTINCT user_id FROM Logins WHERE date = '2023-01-01') a LEFT JOIN (SELECT DISTINCT user_id FROM Logins WHERE date = '2023-01-02') b ON a.user_id = b.user_id;

8. 附录:实用工具脚本

8.1 测试数据生成器

import random import pymysql def generate_employees(count=100): departments = ['HR', 'Engineering', 'Marketing', 'Finance'] conn = pymysql.connect(host='localhost', user='root', password='123456', database='leetcode') with conn.cursor() as cursor: for i in range(1, count+1): name = f'Employee_{i}' dept = random.choice(departments) salary = random.randint(3000, 15000) cursor.execute( "INSERT INTO Employees VALUES (%s, %s, %s, %s)", (i, name, dept, salary) ) conn.commit()

8.2 执行计划可视化工具

使用MySQL Workbench的Visual Explain功能,可以图形化查看执行计划:

  1. 编写查询语句
  2. 点击"Execution Plan"标签
  3. 分析各节点的成本占比

9. 面试高频考点

根据近期面试经验整理的高频考点:

  1. JOIN原理

    • Nested Loop Join实现机制
    • Hash Join的适用场景
  2. 索引优化

    • 最左前缀原则实例
    • 覆盖索引的优势
  3. 事务隔离

    • 脏读/幻读的复现
    • MVCC实现原理
  4. 分库分表

    • 水平拆分策略
    • 分布式ID生成方案

10. 持续提升建议

完成LeetCode题库后,建议向这些方向深入:

  1. MySQL源码研究

    • 查询优化器工作流程
    • InnoDB存储引擎架构
  2. 性能基准测试

    • sysbench压力测试
    • 慢查询日志分析
  3. 分布式数据库

    • 主从复制原理
    • 分片集群部署
  4. 云数据库实践

    • RDS参数调优
    • 读写分离配置

我个人的学习路径是:LeetCode刷题 → 《高性能MySQL》→ MySQL源码调试 → 分布式方案实践。每个阶段都需要用实际项目验证理论,才能真正消化知识。