大家好呀,我是31岁的小米,一个对技术痴迷、爱分享故事的大哥哥。上周末在咖啡馆里,我经历了一场“心跳加速”的面试模拟,把我逼出了新高度。面试官抛来的一句话就让我脑子里闪过无数个 SQL 片段,他问我——
“小米,能不能聊聊你对 MySQL 子查询的理解?它有哪些情况?”
当时我差点一口咖啡呛出来,心里喊着:“这不是我刚刚复习过的吗?幸好昨天晚上临时抱佛脚了!”
今天呢,我就把当时的回答和我平时踩过的坑,整理成一篇长文,分享给正在准备面试的小伙伴们。别小看这道题,它经常在社招面试里出现,而且考察的不只是你会写 SQL,而是你能不能把原理+场景讲透。
什么是子查询?
先来个故事开场。
有一次我和朋友去吃火锅,我们点了一堆菜。朋友突然问我:
“小米,咱们今天吃的肉里面,哪一盘是最便宜的?”
我翻菜单的时候,脑子里就形成了两步逻辑:
- 先查出所有肉类的价格
- 再在这些价格中,选出最便宜的那一盘
这其实就是“子查询”的思路。
子查询(Subquery) ,顾名思义,就是一条 SQL 语句嵌套在另一条 SQL 语句里,它的查询结果会作为外层查询的条件或者数据来源。
换句话说:
- 条件:子查询的结果,可以作为外层 SQL 的查询条件
- 嵌套:子查询本身是 SQL 的一部分,像一个“临时助手”,帮助外层 SQL 完成任务
总结一句话:子查询就是把一个查询的结果,当成另一个查询的输入。
子查询的两大特征
子查询虽然听起来高级,其实有两个特征特别容易记:
- 条件特征: 子查询的结果,常常作为父查询的条件使用,比如 WHERE、HAVING、FROM、SELECT 里都能出现。
- 嵌套特征: 子查询一定是嵌套的,内部 SQL 的结果得先出来,才能被外部 SQL 用到。
所以你可以把子查询理解成“先打草稿,再给最终答卷”。
子查询的三种情况
好了,接下来进入重头戏,也是面试官最关心的地方:子查询分三种情况。
这三种情况,就像三个层次的火锅套餐,从“一个小菜”到“一整桌宴席”,层层递进。
单行单列的子查询 —— 返回一个值
这种情况最简单,就像你问我:
“小米,你朋友里谁年龄最小?”
我查一圈,结果只有一个人,一个年龄。SQL 写出来就是这样:
这里 (SELECT MIN(age) FROM student) 就是一个子查询,它返回的结果只有一行一列,也就是一个值。
所以父查询的条件可以直接用 =、<、> 等运算符去比较。
关键点:
- 单行单列子查询返回的就是一个“具体的值”
- 常常搭配 =、<、> 等运算符使用
这就像单选题,答案只有一个。
多行单列的子查询 —— 返回一个数组
如果换个问题:
“小米,班里哪些同学的成绩在前 3 名?”
这时候结果就不是一个人,而是三个人。返回的就是一个“数组”。SQL 可以这么写:
这里 (SELECT score FROM student ORDER BY score DESC LIMIT 3) 返回了多个分数,但是只有一列。父查询就可以用 IN 来判断。
关键点:
- 多行单列子查询返回的结果像一个数组
- 常常搭配 IN、ANY、ALL 等关键字使用
比如:
- IN 表示“在这些结果里”
- ANY 表示“和其中任意一个比较”
- ALL 表示“和所有结果比较”
这就像多选题,有多个答案可以选。
多行多列的子查询 —— 返回一张虚拟表
最后一种情况就比较有意思了,它返回的不是一个值,也不是一列,而是一张表。
比如:
“小米,给我一份‘平均分高于 80 的所有班级名单和平均分’。”
这时候子查询必须先算出每个班级的平均分,再筛选出大于 80 的班级,最后外层 SQL 再来用。SQL 写法:
这里 (SELECT class, AVG(score) ... ) 就是一张“虚拟表”,外层查询可以直接在这张虚拟表上再做过滤。
关键点:
- 多行多列子查询返回的结果是一张临时表
- 不能直接用于 WHERE 条件
- 常常用于 FROM 子句,或者 SELECT 子句
这就像是“整套题卷子”,外层 SQL 可以把它当一张表来继续查询。
三个场景的对比总结
一句话总结:
- 单行单列 = 单选题
- 多行单列 = 多选题
- 多行多列 = 表格题
真实面试小故事
我当时在面试现场,就是按这个逻辑回答的:
- 先解释子查询是什么(条件 + 嵌套)
- 再分三种情况,举了例子
- 最后做了个总结对比表格
面试官笑着点头,说:“嗯,小米回答得很清晰,说明你不光会写,还能讲明白逻辑。”
那一刻,我内心 OS:这回应该稳了!
子查询的坑点与优化
说了这么多,别忘了子查询也有坑。比如:
- 性能问题: 子查询如果结果集很大,容易拖慢查询速度。很多时候可以用 JOIN 来代替子查询。
- 可读性问题: 子查询层级太深时,SQL 可读性差,维护麻烦。建议加别名,逻辑拆清楚。
- LIMIT 陷阱: 有些子查询里加 LIMIT 会报错,尤其是当它出现在 IN 子句里时,要注意 SQL 方言的兼容性。
所以,不要盲目地觉得子查询万能。面试官如果追问,你也可以顺势补一句:
“子查询虽然方便,但在大数据量场景下我更倾向于用 JOIN 来优化性能。”
这样回答,绝对加分。
写在最后
子查询,是 SQL 世界里的一把瑞士军刀,灵活好用,场景丰富。它考察的不仅是你能不能写出 SQL,还考察你能不能把复杂逻辑分解成多个小步骤,再组合起来。
我常跟小伙伴说,学 SQL 就像打游戏,你得知道武器什么时候用,怎么用才高效。子查询,就是那把灵巧的小刀,用得好能轻松过关,用不好就会卡死在性能里。
希望这篇文章能帮你在面试中游刃有余。下次遇到面试官抛来这道题的时候,你也能自信地笑一笑,说:
“子查询嘛,分三种情况:单行单列、多行单列、多行多列。”
面试官一定会对你刮目相看。
END
如果这篇文章对你有帮助,记得点个赞呀! 我会继续分享更多面试高频 SQL 知识点,让我们一起从容应对社招面试!
我是小米,一个喜欢分享技术的31岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货!