精选19道SQL面试题:覆盖查询、概念与常见陷阱

1. 找出第二高的薪水。

经典老题。毕竟,谁的梦想不是当第二名呢?(手动狗头)

复制代码
SELECT MAX(salary)
FROM employees
WHERE salary < (SELECT MAX(salary) FROM employees);

2. 找出表中的重复记录。

重复记录就像你的前任。你巴不得他们消失,但他们总阴魂不散。

复制代码
SELECT column_name, COUNT(*)
FROM table_name
GROUP BY column_name
HAVING COUNT(*) > 1;

3. 找出从未提交过报告的员工。

可以称之为 SQL 版的"绩效考核"或"末位淘汰提醒器"。

复制代码
SELECT e.id, e.name
FROM employees e
LEFT JOIN reports r ON e.id = r.emp_id
WHERE r.emp_id IS NULL; -- 如果在 reports 表中没有记录,则 r.emp_id 为 NULL

4. 找出第 N 高的薪水。

又名:"这查询能把我脑浆子都榨干。" / "这题谁爱做谁做!"

复制代码
-- 假设 N 是你想找的排名,比如 N=3 就是第三高
SELECT DISTINCT salary
FROM employees e1
WHERE (N - 1) = ( -- 注意:这里 N 需要替换成具体数字,例如 3-1 = 2
  SELECT COUNT(DISTINCT e2.salary)
  FROM employees e2
  WHERE e2.salary > e1.salary
);
-- 更好的方法通常是使用窗口函数,比如 ROW_NUMBER(), RANK(), DENSE_RANK()

5. 解释一下 CROSS JOIN (交叉连接)。

简而言之:它就是你一不小心搞出一百亿行数据,然后被DBA追杀的方法。

复制代码
SELECT * FROM A CROSS JOIN B; -- A 表的每一行与 B 表的每一行组合

6. 找出员工数超过5人的部门。

因为没什么比"超过五个"更能喊出"我们部门牛逼!"的口号了。(然而并不能)

复制代码
SELECT department_id, COUNT(*)
FROM employees
GROUP BY department_id
HAVING COUNT(*) > 5;

7. 使用 ROW_NUMBER() 找出每个部门收入最高的前3名员工。

献给那些在 SQL 世界里追求"高端操作"的人。

复制代码
SELECT *
FROM (
  SELECT 
    e.*, 
    ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC) AS rn
  FROM employees e
) ranked_employees
WHERE rn <= 3;

8. 使用自连接 (Self Join) 找出员工及其经理的配对。

SQL 版《盗梦空间》。一张表自己连接自己,能出啥岔子呢?(最好别出)

复制代码
SELECT e.name AS employee, m.name AS manager
FROM employees e
JOIN employees m ON e.manager_id = m.id;

9. WHERE vs. HAVING:搏击俱乐部特别版。
WHERE 在分组 筛选数据。HAVING 在分组筛选聚合结果。还是一头雾水?放心,你面试官也可能一样。

10. 删除重复记录,但保留一条。

又名:"求求了,手下留情,可别把整个表给干没了啊。"

复制代码
-- 假设我们根据 email 列去重,保留 id 最小的那条记录
DELETE FROM employees
WHERE id NOT IN (
  SELECT MIN(id) -- 找出每个 email 分组中 id 最小的那个
  FROM employees
  GROUP BY email
);
-- 注意:这个操作有风险,请先备份数据,并在测试环境验证!

11. 将行数据转换为列数据 (Pivot / 行转列)。

面试官:"用 SQL 实现这个。"

你 (内心OS):"图啥呢?直接代码里处理不香吗?"

12. 使用 EXISTS

因为用 IN 显得你太菜了,不够秀。

复制代码
SELECT s.name
FROM students s
WHERE EXISTS ( -- 检查是否存在
  SELECT 1
  FROM grades g
  WHERE g.student_id = s.id -- 相关的成绩记录
);

13. 解释一下数据库范式 (Normalization)。

哦,你是指那个在 NoSQL 横行的时代里,好像没几个人真正鸟的玩意儿?

14. 相关子查询 (Correlated Subqueries)。

你又在跟自己 JOIN 了,只不过这次换了个马甲。你还好吗,哥们?需要心理疏导不?

复制代码
-- 找出薪水高于其所在部门平均薪水的员工
SELECT e.name, e.salary
FROM employees e
WHERE e.salary > (
  SELECT AVG(s.salary)
  FROM employees s
  WHERE s.department_id = e.department_id -- 子查询依赖外部查询的 e.department_id
);

15. 找出两张表共有的记录 (Common records between two tables)。

SQL 版的"陌陌点赞,配对成功"。

复制代码
SELECT * FROM A
INTERSECT -- 交集操作
SELECT * FROM B;

16. 按部门更新薪水。

就是那个你的 UPDATE 查询一不小心就可能让公司 CFO 菊花一紧的时刻。

复制代码
UPDATE employees
SET salary = salary * 1.1 -- 比如给 10 号部门涨薪 10%
WHERE department_id = 10;
-- 千万别忘了 WHERE 条件!不然就是P0级事故!

17. 找出没有下属的经理。

数据库里的社恐本恐,或者光杆司令。

复制代码
SELECT e.name
FROM employees e
WHERE e.is_manager = TRUE -- 假设有个字段标记是否为经理(或者在 manager 表中)
  AND e.id NOT IN (
    SELECT DISTINCT manager_id -- 找出所有被别人作为经理ID引用的ID
    FROM employees
    WHERE manager_id IS NOT NULL
  );
-- 更简单的可能是:
-- SELECT m.name FROM employees m LEFT JOIN employees e ON m.id = e.manager_id WHERE m.is_manager = TRUE AND e.id IS NULL;

18. 将行转置为列 (Transpose rows into columns)。

因为你老板觉得 SQL 就应该跟 Excel 一样万能,点几下就能出透视表。

19. 找出销量最高的前3名商品。

因为"排名 = 营收"嘛。至少老板是这么PUA我们的。

复制代码
SELECT item, COUNT(*) AS freq
FROM sales
GROUP BY item
ORDER BY freq DESC
LIMIT 3;
相关推荐
MyikJ1 小时前
互联网大厂Java面试:从Spring到微服务的挑战
数据库·spring boot·微服务·saas·java面试·缓存技术
车载诊断技术1 小时前
基于物联网(IoT)的电动汽车(EVs)智能诊断
数据库·物联网·架构·汽车·电气电子架构开发的应对策略·车辆诊断技术全生命周期管理
echola_mendes1 小时前
Mac安装MongoDB数据库以及MongoDB Compass可视化连接工具
数据库·mongodb
心想好事成2 小时前
尚硅谷redis7 47-48 redis事务之理论简介
java·数据库·redis
搞不懂语言的程序员2 小时前
如何通过ES实现SQL风格的查询?
sql·elasticsearch·jenkins
静思心远2 小时前
ubuntu2x.xx网络不通如何解决
网络·数据库·postgresql
码上库利南2 小时前
详解MYSQL索引失效问题排查
数据库·mysql
遥遥领先zzl3 小时前
实时数仓flick+clickhouse启动命令
运维·服务器·数据库
Cachel wood3 小时前
Mysql常用知识3:Kafka和数据库优化
数据库·mysql·kafka
会敲键盘的猕猴桃很大胆3 小时前
Redis实战-缓存篇(万字总结)
java·数据库·spring boot·redis·缓存