
SQL面试高频问题解析
SQL面试通常不考死记硬背,而是看是否真正理解数据操作逻辑、能否用SQL解决实际业务问题。高频题集中在多表关联、聚合分析、窗口函数、去重与排序、NULL处理、分页与TopN这几类,下面逐个拆解关键点和易错细节。
多表连接(JOIN)的逻辑与陷阱
面试常问:INNER JOIN / LEFT JOIN 的区别?ON 和 WHERE 条件位置不同会怎样?
- LEFT JOIN 保留左表全部记录,右表无匹配则补 NULL;INNER JOIN 只返回两表都存在的交集
- ON 是连接条件,决定如何“配对”;WHERE 是连接完成后的过滤——把条件写在 ON 里可能影响连接结果,写在 WHERE 里可能把 LEFT JOIN “变成” INNER JOIN(比如 WHERE 右表字段 IS NOT NULL)
- 常见错误:用 LEFT JOIN 后加 WHERE b.id > 0,却没意识到这会过滤掉右表为 NULL 的行,实际丢失了左表独有数据
GROUP BY 与聚合函数的配合要点
GROUP BY 不是简单“按某列分组”,它定义了结果集的粒度,SELECT 中所有非聚合字段必须出现在 GROUP BY 子句中(MySQL 5.7+ 默认开启 ONLY_FULL_GROUP_BY 才强制校验)。
- 错误写法:
SELECT user_id, name, COUNT(*) FROM orders GROUP BY user_id—— name 没参与分组,数据库无法确定返回哪个 name - 正确思路:要么把 name 加入 GROUP BY,要么用聚合函数包裹(如 MAX(name)),前提是业务允许取任意一个或最值
- HAVING 用于过滤分组后结果,WHERE 过滤分组前数据;HAVING 可用聚合函数,WHERE 不可以
窗口函数:TopN、排名、累计计算的核心工具
窗口函数是区分初级和进阶 SQL 能力的关键,面试中出现频率极高,尤其在用户行为分析、销售排行、同比环比场景。
- ROW_NUMBER() / RANK() / DENSE_RANK():三者区别在于并列时的编号策略,ROW_NUMBER 不重复不跳号,RANK 并列跳号,DENSE_RANK 并列不跳号
- 常用结构:
OVER (PARTITION BY 分组字段 ORDER BY 排序字段),PARTITION BY 可省略(全表视为一组) - 典型题:查每个部门工资最高的员工(含并列)→ 用 RANK() 或 DENSE_RANK(),再 WHERE rn = 1;若只取一条,用 ROW_NUMBER() 更稳妥
NULL 值处理与常见函数避坑
NULL 在 SQL 中不是值,而是“缺失”标记,所有涉及 NULL 的比较(=、!=、>)都返回 UNKNOWN,导致逻辑失效。
- 判断空用
IS NULL或IS NOT NULL,别用= NULL - 聚合函数自动忽略 NULL(COUNT(*) 统计行数,COUNT(列) 忽略该列 NULL 值)
- COALESCE(a, b, c) 返回第一个非 NULL 值,比 CASE WHEN 简洁;NULLIF(a,b) 当 a=b 时返回 NULL,否则返回 a,适合做条件屏蔽
分页与性能意识:从 LIMIT OFFSET 到游标分页
基础分页用 LIMIT m OFFSET n 简单直接,但大数据量下 OFFSET 越大越慢(数据库仍需扫描前 n+m 行)。面试官可能追问优化方案。
- 推荐游标分页(Cursor-based Pagination):用上一页最后一条记录的排序字段值作为下一页起点,例如
WHERE id > 1000 ORDER BY id LIMIT 20 - 避免 SELECT *,只查必要字段;JOIN 前先用 WHERE 过滤小表,减少中间结果集
- 索引要覆盖 ORDER BY + WHERE + JOIN 条件字段,尤其注意联合索引最左前缀原则










