1. SQL 实战训练从基础到进阶的 14 道核心题目解析作为一名长期与数据库打交道的开发者我深知 SQL 能力在后端开发中的重要性。最近在准备面试和复习 SQL 时我系统性地整理了力扣上的 14 道高频 SQL 题目这些题目覆盖了从基础到进阶的各种场景。今天我想分享这些题目的详细解析希望能帮助到同样在准备面试或想提升 SQL 能力的同学。这 14 道题不是随机挑选的而是精心设计来训练 4 个核心能力的条件过滤WHERE 子句的灵活运用多表关联各种 JOIN 的使用场景聚合统计GROUP BY 与聚合函数的配合NULL 值的正确处理这是很多面试的考察重点如果你能完全掌握这 14 道题就能建立起从业务需求到 SQL 语句的转化能力这在后端开发面试中是非常关键的技能。2. 基础筛选WHERE 子句的精确使用2.1 单条件筛选1757. 可回收且低脂的产品业务场景我们有一个产品表需要找出同时满足低脂和可回收两个条件的产品。SELECT product_id FROM Products WHERE low_fats Y AND recyclable Y;关键点这是一个典型的单表多条件查询使用 AND 连接多个条件表示必须同时满足注意字段值是 Y/N 这种枚举值不是布尔值常见错误写成low_fats Y OR recyclable Y这会返回满足任一条件的产品忽略大小写问题如果数据不规范可能有 y/n 的情况2.2 NULL 值处理584. 寻找用户推荐人业务场景找出所有推荐人不是 2 的用户包括那些没有推荐人的用户。SELECT name FROM Customer WHERE referee_id ! 2 OR referee_id IS NULL;为什么这样写SQL 中 NULL 表示未知任何与 NULL 的比较都返回 UNKNOWNreferee_id ! 2会过滤掉 NULL 值必须显式加上IS NULL条件这是 SQL 面试中最常考察的 NULL 处理场景错误示范-- 这样会漏掉 referee_id 为 NULL 的用户 SELECT name FROM Customer WHERE referee_id ! 2;2.3 多条件筛选595. 大的国家业务场景找出面积大于 300 万或人口大于 2500 万的国家。SELECT name, population, area FROM World WHERE area 3000000 OR population 25000000;关键点使用 OR 连接条件表示满足任一即可注意数值的单位和大小300万3000000这类题目考察对 WHERE 子句中逻辑运算符的理解3. 表连接数据关系的建立3.1 自连接197. 上升的温度业务场景找出比前一天温度更高的日期。SELECT w1.id FROM Weather w1 JOIN Weather w2 ON DATEDIFF(w1.recordDate, w2.recordDate) 1 AND w1.temperature w2.temperature;为什么需要自连接需要比较同一表中不同行的数据通过别名创建表的两个实例使用 DATEDIFF 函数确保比较的是相邻两天性能考虑大数据量时DATEDIFF 可能效率不高可以考虑使用日期加减函数优化3.2 左连接1378. 使用唯一标识码替换员工ID业务场景显示所有员工信息有唯一标识码的显示没有的显示 NULL。SELECT e.name, u.unique_id FROM Employees e LEFT JOIN EmployeeUNI u ON e.id u.id;左连接特点保留左表Employees所有记录右表EmployeeUNI没有匹配的记录显示为 NULL这是处理可能有关联数据场景的标准做法3.3 交叉连接1280. 学生们参加各科测试的次数业务场景统计每个学生参加每门科目的考试次数包括0次。SELECT s.student_id, s.student_name, sub.subject_name, COUNT(e.subject_name) AS attended_exams FROM Students s CROSS JOIN Subjects sub LEFT JOIN Examinations e ON s.student_id e.student_id AND sub.subject_name e.subject_name GROUP BY s.student_id, sub.subject_name;为什么用 CROSS JOIN需要学生和科目的所有组合CROSS JOIN 生成笛卡尔积再通过 LEFT JOIN 关联实际考试记录COUNT 计算实际参加次数NULL 不计数4. 聚合统计数据汇总与分析4.1 基础聚合570. 至少有 5 名直接下属的经理业务场景找出直接下属不少于5人的经理。SELECT m.name FROM Employee e JOIN Employee m ON e.managerId m.id GROUP BY m.id HAVING COUNT(e.id) 5;关键点自连接找出上下级关系GROUP BY 按经理分组HAVING 对聚合结果过滤WHERE 不能用于聚合函数COUNT 计算每个经理的下属数量4.2 复杂聚合1934. 确认率业务场景计算每个用户的确认率confirmed请求数/总请求数。SELECT s.user_id, ROUND( SUM(CASE WHEN c.action confirmed THEN 1 ELSE 0 END) / COUNT(*), 2 ) AS confirmation_rate FROM Signups s LEFT JOIN Confirmations c ON s.user_id c.user_id GROUP BY s.user_id;高级技巧使用 CASE WHEN 条件计数注意除以 COUNT(*) 可能为0的情况此题保证至少一次请求ROUND 保留两位小数LEFT JOIN 确保所有用户都包含4.3 时间差计算1661. 每台机器的进程平均运行时间业务场景计算每台机器上进程的平均运行时间。SELECT machine_id, ROUND(AVG(end_t.timestamp - start_t.timestamp), 3) AS processing_time FROM Activity start_t JOIN Activity end_t ON start_t.machine_id end_t.machine_id AND start_t.process_id end_t.process_id AND start_t.activity_type start AND end_t.activity_type end GROUP BY machine_id;时间计算要点自连接匹配同一进程的 start 和 end 记录直接相减得到运行时间AVG 计算平均值ROUND 保留三位小数5. 实战经验与避坑指南在实际编写 SQL 和处理这些题目时我总结了一些重要的经验教训NULL 处理要特别小心任何与 NULL 的比较操作都返回 UNKNOWN聚合函数如 COUNT、SUM 会忽略 NULL使用 IS NULL/IS NOT NULL 显式检查JOIN 类型选择很重要INNER JOIN只保留两表匹配的记录LEFT JOIN保留左表所有记录RIGHT JOIN保留右表所有记录较少使用FULL JOIN保留两表所有记录CROSS JOIN生成笛卡尔积GROUP BY 的注意事项SELECT 中的非聚合字段必须出现在 GROUP BY 中WHERE 在 GROUP BY 之前过滤HAVING 在之后过滤聚合函数结果可以用 HAVING 过滤性能优化技巧尽量避免在 JOIN 条件中使用函数合理使用索引特别是 JOIN 和 WHERE 涉及的字段大数据量时考虑分页查询SQL 编写规范使用表别名提高可读性复杂查询适当添加注释保持一致的缩进和格式这套题目从基础到进阶覆盖了 SQL 最核心的几个方面。我建议初学者可以按照以下步骤练习先自己尝试写出 SQL对比标准答案理解差异思考为什么这样写最优尝试不同的写法比较执行计划总结每种题型的解题模式在实际面试中SQL 问题往往不是考察你能写出多么复杂的查询而是看你是否能准确理解业务需求并用最合适的 SQL 表达出来。这 14 道题基本涵盖了面试中 80% 的 SQL 考察点掌握它们能大大提升面试信心。