LeetCode SQL入门:8道基础题掌握80%查询场景
1. LeetCode SQL 阶段0:8道基础题精解
最近在帮团队新人做SQL入门培训时,发现很多同学虽然看过SQL语法,但遇到实际问题时还是无从下手。这让我想起自己当年刷LeetCode SQL题的经历——从最基础的SELECT开始,通过8道典型题目就能掌握80%的日常查询场景。下面就用这8道经典题为例,带大家系统梳理SQL基础操作。
提示:本文所有题目均来自LeetCode免费题库,使用MySQL语法标准,适合零基础或需要巩固基础的开发者
2. 基础查询:SELECT核心四件套
2.1 简单查询与条件过滤
题目175. 组合两个表(难度:简单)要求从Person表和Address表中联合查询姓名和地址信息。这道题考察最基础的:
SELECT p.FirstName, p.LastName, a.City, a.State FROM Person p LEFT JOIN Address a ON p.PersonId = a.PersonId这里有几个关键点:
- 必须使用LEFT JOIN保证没有地址的人也能显示
- 表别名(p/a)让代码更简洁
- SELECT字段明确指定来源表避免歧义
踩坑记录:早期我常忘记写ON条件导致笛卡尔积,结果集暴涨百万倍!
2.2 数据筛选与排序
题目176. 第二高的薪水(难度:简单)演示了WHERE和LIMIT的经典组合:
SELECT ( SELECT DISTINCT Salary FROM Employee ORDER BY Salary DESC LIMIT 1 OFFSET 1 ) AS SecondHighestSalary特别注意:
- 子查询解决"没有第二高时返回null"的要求
- DISTINCT避免相同薪水重复计数
- OFFSET 1跳过第一条记录
3. 条件逻辑与分组统计
3.1 CASE WHEN条件分支
题目177. 第N高的薪水(难度:中等)需要创建函数返回第N高的薪水:
CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT BEGIN SET N = N - 1; RETURN ( SELECT DISTINCT salary FROM employee ORDER BY salary DESC LIMIT 1 OFFSET N ); END这个解法揭示了LIMIT OFFSET的数学本质:
- OFFSET N = 跳过前N条
- 所以N需要减1才能对应题目描述
3.2 分组统计与HAVING
题目178. 分数排名(难度:中等)展示了窗口函数的威力:
SELECT score, DENSE_RANK() OVER (ORDER BY score DESC) AS 'rank' FROM Scores对比三种排名函数:
- RANK(): 并列会跳过后续名次(1,2,2,4)
- DENSE_RANK(): 并列不跳名次(1,2,2,3)
- ROW_NUMBER(): 强制连续(1,2,3,4)
4. 多表操作与复杂逻辑
4.1 自连接查询
题目180. 连续出现的数字(难度:中等)需要找出至少连续出现三次的数字:
SELECT DISTINCT l1.Num AS ConsecutiveNums FROM Logs l1 JOIN Logs l2 ON l1.Id = l2.Id - 1 JOIN Logs l3 ON l2.Id = l3.Id - 1 WHERE l1.Num = l2.Num AND l2.Num = l3.Num关键技巧:
- 通过Id-1实现行与下一行的关联
- 三重自连接确保连续三次
- DISTINCT去重相同数字
4.2 子查询优化
题目181. 超过经理收入的员工(难度:简单)演示了自连接的另一种用法:
SELECT e1.Name AS Employee FROM Employee e1 JOIN Employee e2 ON e1.ManagerId = e2.Id WHERE e1.Salary > e2.Salary性能对比:
- 子查询版本(效率低):
SELECT Name FROM Employee e1 WHERE Salary > (SELECT Salary FROM Employee WHERE Id = e1.ManagerId) - 自连接版本在大数据量时性能更优
5. 实战问题排查指南
5.1 常见错误代码速查
| 错误现象 | 可能原因 | 解决方案 |
|---|---|---|
| 结果为空 | 连接条件错误 | 检查ON后字段是否关联正确 |
| 重复数据 | 忘记DISTINCT | 添加DISTINCT或检查GROUP BY |
| 性能低下 | 全表扫描 | 对WHERE条件字段建立索引 |
5.2 执行计划分析技巧
以题目182. 查找重复的电子邮箱为例:
-- 原始写法 SELECT Email FROM Person GROUP BY Email HAVING COUNT(*) > 1 -- 优化写法(使用临时表) WITH email_counts AS ( SELECT Email, COUNT(*) as cnt FROM Person GROUP BY Email ) SELECT Email FROM email_counts WHERE cnt > 1使用EXPLAIN分析可以看到:
- 原始写法需要全表扫描
- 优化写法能利用索引(如果有)
6. 进阶学习路线建议
完成这8道题后,可以继续挑战:
- 窗口函数进阶(LEAD/LAG等)
- 递归CTE查询
- 复杂JOIN优化
- 索引设计与优化
我个人的学习心得是:每道题至少尝试两种解法,比较执行计划差异。比如题目185. 部门工资前三高的员工,既可以用窗口函数:
SELECT Department, Employee, Salary FROM ( SELECT d.Name AS Department, e.Name AS Employee, e.Salary, DENSE_RANK() OVER (PARTITION BY d.Name ORDER BY e.Salary DESC) AS rnk FROM Employee e JOIN Department d ON e.DepartmentId = d.Id ) t WHERE rnk <= 3也可以用相关子查询实现,后者在MySQL 5.7以下版本可能性能更好。