用一晚掌握SQL基础面试题,按SELECT、WHERE、GROUP BY、JOIN、NULL顺序梳理核心考点,附30分钟练习法,面试前快速提分别错过
你只有一个晚上。不是一周,也不是一个周末——只有一个晚上,要停止觉得自己在 SQL 上总是落后,并开始觉得自己已经足够准备好走进筛选面试而不至于大脑一片空白。好消息是,入门级的 sql basic interview questions 总是在围绕同一小组概念打转。坏消息是,大多数学习资料会丢给你一份 80 个问题的清单然后祝你好运,而这往往是最快让你什么有用的东西都记不住的方式。
这份指南的思路不同。它按照面试官真正介绍概念的顺序来组织内容——从 SELECT 和 WHERE 开始,再到 GROUP BY 和 HAVING,最后落到 joins、keys,以及那些会悄悄让候选人丢掉容易分数的 NULL 陷阱。如果你按照最后的 30 分钟练习流程来做,你就能清晰地把答案说出来,而这才是真正的考核。
你在学其他内容之前必须掌握的 10 个 SQL 基础
面试中,初学者最先应该记住的核心 SQL 基础是什么?
大多数初学者都会掉进一个陷阱:在连最基本的问题都回答不上来之前,就想把所有内容都覆盖到。面试里的 SQL 基础是有天然层级的,忽略这一点就会导致你花两个小时学窗口函数,却仍然搞不清为什么需要 GROUP BY。
真正重要的入门顺序是:SELECT 和 FROM(如何请求数据)、WHERE(如何过滤行)、ORDER BY(如何排序结果)、GROUP BY(如何按类别汇总)、HAVING(如何在汇总后过滤),以及三种关键类型——primary、unique 和 foreign。其他所有内容——子查询、CTE、窗口函数、存储过程——都是建立在这些基础之上的。先把地基打牢。
根据真实招聘经验,入门级最容易准备过头的话题是子查询。候选人往往能流利解释相关子查询,却在被问到为什么需要 HAVING 时卡住。稳定来看,准备最不足的话题是 NULL 的行为。它几乎会出现在每一场筛选面试里,并且经常绊倒那些本来查询直觉不错的人。
你会如何向一个从没用过 SQL 的人解释 SQL?
最通俗的说法大概是这样:“SQL 是一种用来向数据库提问的语言。数据库把信息存成表——也就是行和列,像电子表格一样。SQL 让你说:给我这张表里满足这个条件、并按这种方式排序的那些行。”
如果你需要一个具体例子,就用员工和部门。你有一个 `employees` 表,里面有 `name`、`salary`、`department_id` 这类列。你还有一个 `departments` 表,里面有 `department_id` 和 `department_name`。SQL 就是用来把这些表连接起来,并准确取出你关心的那些行。这个表述——表、行、列、问题——足够回答初级面试题,而且听起来自然,不像背诵过的。
哪些 SQL 主题会先出现在基础面试里,哪些可以先放一放?
根据 SHRM 的招聘实践指南 和常见公开的技术筛选标准,入门级 SQL 筛选几乎总是先从单表查询开始,然后才引入多表场景。这意味着 SELECT、WHERE、ORDER BY、GROUP BY 和 HAVING 是第一道门槛。Joins 是第二步。子查询和性能相关内容是第三步,如果在基础轮里会出现的话。
可以安全延后、等你有更多时间再学的内容包括:CTE、窗口函数、索引和查询优化、存储过程,以及数据库特有的语法差异。这些内容对中级和高级岗位很重要。对于初学者筛选来说,知道它们是加分项,不是基本要求。
如何把查询基础答得简洁明了
如何在 30 秒内解释 SELECT 和 FROM?
能经得住追问的口头答案是:“SELECT 告诉数据库我想看哪些列。FROM 告诉它要去哪个表里找。所以 `SELECT name, salary FROM employees` 会从 employees 表的每一行里只取这两列。”
接下来通常会被追问的是:“如果你想要所有列呢?”答案是 `SELECT *`,而且你应该立刻补一句:在生产代码里通常会避免这样做,因为它会取出不必要的数据。多这一句话就能表明你理解真实世界中的取舍,而不仅仅是语法。对于基础 SQL 面试题来说,这种区分往往正是区分“能过”和“答得好”的地方。
如何解释 WHERE,而不把它和 HAVING 搞混?
WHERE 是在任何分组或聚合发生之前过滤行。这就是全部区别,而且值得你原封不动地这么说。
一个具体例子是:“我有一张 `orders` 表。`WHERE amount > 100` 会只给我金额超过 100 美元的订单——它过滤的是单独的行。这就是 WHERE。” 候选人常犯的错误是在 GROUP BY 之后还想用 WHERE,但 SQL 不允许这样做。WHERE 不知道什么是“组”。它只认识行。记住这个画面——WHERE 看的是行,HAVING 看的是组——你就能在压力之下不犹豫地回答这个区别问题。 PostgreSQL 官方文档 对聚合的说明明确写出了这个顺序:WHERE 先于分组执行,HAVING 在分组之后执行。
如何在一分钟内清楚解释 ORDER BY 和 GROUP BY?
这两个概念之所以容易混淆,是因为它们都会改变结果的显示方式,但它们做的事情完全不同。
ORDER BY 负责排序。`ORDER BY salary DESC` 给你的还是同样那些行,只是按工资从高到低排好序。没有合并,没有汇总——只是重新排列输出。GROUP BY 负责汇总。`GROUP BY department_id` 会把同一个部门的所有行压缩成一行,这样你就能问聚合问题:每个部门有多少员工、每个部门的平均工资是多少。一个是排序,一个是汇总。显示按地区划分的总销售额的报表会用 GROUP BY。显示销售额前 10 名员工的报表会用 ORDER BY。
当面试官想要简短版本时,如何解释 HAVING?
一句话就够了:“HAVING 过滤的是 GROUP BY 的结果,就像 WHERE 过滤单独的行一样。” 然后马上补个例子,因为光这句话听起来像是你背下来的定义。
例如:“如果我按销售员分组销售额,并且只想看总销售额超过 10,000 美元的销售员,我不能用 WHERE——因为此时还没有某一行的总额。我应该在 GROUP BY 之后使用 `HAVING SUM(amount) > 10000`。” 这个答案足够具体,能经得住追问,同时又足够简短,不会跑题。
下面对比一下模糊回答和清晰回答。模糊版:“HAVING 就像针对组的 WHERE。” 清晰版:“WHERE 在分组之前过滤行。HAVING 过滤分组后的结果。如果你尝试在 WHERE 阶段对 SUM 或 COUNT 这样的聚合函数使用条件,SQL 会报错——因为在 WHERE 阶段,这些聚合还没有计算出来。” 第二种回答可以经得住追问,第一种不行。
Keys、约束,以及面试官用来判断你是不是真的懂表的内容
primary key、unique key 和 foreign key 有什么区别?
关于 key 的入门级 SQL 问题经常让候选人卡住,因为这些定义听起来很像,直到你把它们分别对应到实际约束的内容。
Primary key:唯一标识表中的每一行,不能是 NULL,而且每张表只能有一个。在 `employees` 表中,`employee_id` 就是 primary key——每个员工都只有一个,而且不会有两个员工共用同一个。Unique key:同样保证唯一性,但在大多数数据库中它可以允许 NULL,而且一张表可以有多个 unique key。`email` 列就是典型的 unique key——两个用户不能共用同一个邮箱,但它不一定是 primary key。Foreign key:把一张表和另一张表连接起来。`employees` 表里的 `department_id` 就是一个 foreign key,引用的是 `departments` 表中的 `department_id`。它确保你不能把员工分配到一个不存在的部门。
SQL 约束在真实表里到底做什么?
把约束想成护栏,它们会在坏数据进入表之前把它拦住。NOT NULL 表示某列不能为空——如果你试图插入一行却缺少必填值,数据库会拒绝。CHECK 添加一个条件:`CHECK (age >= 18)` 表示年龄小于 18 的行不能插入。UNIQUE 防止某列出现重复值。PRIMARY KEY 把 NOT NULL 和 UNIQUE 合并成一个约束。
注册表单是最清楚的现实例子。`users` 表里 `email` 用 UNIQUE(不能有重复账号),`username` 用 NOT NULL(不能没有用户名),`user_id` 用 PRIMARY KEY。如果没有这些约束,坏数据就会悄悄混进来——重复邮箱、空用户名、没有标识符的行——而之后再清理的代价,远高于在表层直接拦截。想看每种约束在你所用方言中的准确语法,可以参考 MySQL 关于约束的文档。
为什么面试官在初级阶段也会在意规范化?
在初级层面,规范化只意味着一件事:不要把同一个事实存到多个地方。如果你有一个 `customers` 表和一个 `orders` 表,客户地址应该放在 `customers` 里,而不是在 `orders` 的每一行里重复存一遍。客户搬家时,你只需要更新一行,而不是几百行。
初学者常见的 schema 错误,是把 `customer_name` 和 `customer_email` 直接放进 `orders` 表。这样一来,如果客户改了邮箱,你就得更新他下过的每一笔订单——只要漏掉一条,数据就不一致了。对初学者来说,规范化不是为了背 1NF、2NF、3NF。它只是为了让你能说出:“我尽量把每个事实只放在一个地方,这样更新会更干净。”
Joins、子查询,以及初学者最容易开始发懵的地方
初级面试题里,什么时候该用 INNER JOIN,什么时候该用 LEFT JOIN?
先说简单规则:INNER JOIN 只返回两张表中都能匹配上的行。LEFT JOIN 返回左表中的所有行,再加上右表中匹配的行——如果右边没有匹配项,就填 NULL。
但简单规则在这里会失效。如果你有一张 `customers` 表和一张 `orders` 表,并且你想看到所有客户,包括那些从未下过单的客户,INNER JOIN 会悄悄把这些客户删掉。LEFT JOIN 会保留他们,并在订单列里显示 NULL。初学者 SQL 面试题里,几乎总会出现“缺失的行”很重要的场景——没有订单的客户、没有经理的员工、没有销量的产品。你要问自己的问题是:“如果没有匹配项,我能接受这些行消失吗?” 如果能,用 INNER JOIN;如果不能,用 LEFT JOIN。 PostgreSQL 关于 join 类型的文档 清楚地解释了完整行为。
如何解释子查询,而不让它听起来很吓人?
子查询就是嵌套在另一个查询里的查询。内层查询先执行并产生结果,外层查询再使用这个结果。就这么简单。
一个更具体的例子是:“我想找出所有工资高于平均工资的员工。我可以先用一个查询算出平均值,再用第二个查询使用这个数字。或者我也可以一步完成:`SELECT name FROM employees WHERE salary > (SELECT AVG(salary) FROM employees)`。” 内层查询负责算平均值。外层查询使用这个结果。两步,一个语句。
在面试里,最快区分 join 和 subquery 的方法是什么?
记忆法:当你需要把两张表里的列都显示在结果中时,用 JOIN。当地你只需要另一张表里的一个值来做过滤或比较时,用子查询。
如果你想把员工和他们的部门名称列在一起,你需要同时取 `employees` 和 `departments` 的列——这就是 JOIN。如果你想找出消费最高的人,但最终结果不需要 `orders` 表里的任何列,子查询往往更简洁。在真正的面试过程中,如果候选人用了本该用 JOIN 的地方去写子查询,通常会因为逻辑正确而拿到部分分,但面试官还是会要求他重写——因为面试官想看他是否明白 JOIN 版本更易读,也更容易利用索引。知道两种写法,并且能说清楚你为什么选其中一种,才是“会做”和“答得好”的分界线。
NULL、DISTINCT 和聚合:那些会悄悄让你丢分的小坑
为什么 NULL 总是把初学者的 SQL 答案搞崩?
NULL 不是 0。它不是空字符串。它表示值未知或不存在,而这个区别会打破普通的比较逻辑。
`WHERE salary = NULL` 永远不会返回任何行,即使某些工资确实是 NULL。SQL 要求你写 `WHERE salary IS NULL`。原因是:NULL 和任何东西比较——甚至和另一个 NULL 比较——结果都不是 TRUE 或 FALSE,而是 NULL。于是这个过滤条件会悄悄把每一行都丢掉。SQL 基础面试题几乎都会包含至少一个 NULL 问题,而能得分的答案是:“NULL 表示未知,所以不能用 = 去找它。你需要用 IS NULL 或 IS NOT NULL。” 一个能说明这点的真实数据清洗例子是:某团队算平均响应时间时得到了一个可疑偏高的数字,因为他们忘了 NULL 的响应时间会被聚合函数排除,而不是当成 0。
如何使用 DISTINCT,而不把数据问题藏起来?
DISTINCT 会从结果中移除重复行。风险在于,你可能只是把一个脏结果修得“看起来整洁”,却没有理解重复为什么会出现。
如果你有一张 `contacts` 表,`SELECT DISTINCT email` 返回的行数少于 `SELECT email`,说明你的数据里有重复邮箱。DISTINCT 在重复是预期内且无害时是正确工具——比如从销售表里取唯一国家列表。但如果重复意味着数据完整性问题,应该在源头修复,那它就不是合适的工具。面试时如果你要用 DISTINCT,要准备好解释为什么有重复,以及去重是否真的正确。
当涉及 NULL 时,SUM、COUNT、AVG、MIN、MAX 哪些地方会出错?
初学者最容易忘记的一条规则是:大多数聚合函数会完全忽略 NULL。`AVG(salary)` 只计算非 NULL 工资的平均值——它不会把 NULL 当成 0。`COUNT(salary)` 只统计非 NULL 的 salary 值。`COUNT(*)` 则不管有没有 NULL,统计所有行。
一个小表例子:五名员工的工资分别是 50,000、60,000、NULL、70,000、NULL。`AVG(salary)` 返回 60,000——这是三个值的平均,而不是五个。`COUNT(salary)` 返回 3。`COUNT(*)` 返回 5。如果你以为 AVG 会把五名员工都算进去,那你的结果就是错的。修正方法通常是在聚合前用 `COALESCE(salary, 0)` 把 NULL 替换成 0——但前提是 0 在业务上确实是正确的解释。
真正能记住内容的 30 分钟练习流程
如果你只有一个晚上,前 10 分钟该怎么用?
第 0 到 10 分钟的重点是回忆,而不是掌握。请在纸上或文本编辑器里写出五个核心子句的顺序:SELECT、FROM、WHERE、GROUP BY、HAVING、ORDER BY。然后给每个子句写一句话说明它的作用。不要查资料。你从记忆里写不出来的内容,就是最先需要复习的部分。
基础 SQL 面试题在筛选阶段几乎总是从这些子句开始。如果你能用一句话解释每一个,并写出一个使用它的简单查询,你就已经过了第一关。这是检索练习,不是阅读——而学习科学关于 心理科学协会的间隔检索研究 一再表明,在时间压力下,主动回忆比被动复习更能帮助记忆。
如果你是完全的初学者,10 到 20 分钟应该练什么?
转到带过滤和分组的单表查询。使用这个提示:“你有一张 `sales` 表,包含 `salesperson`、`region` 和 `amount` 三列。写一个查询,显示按地区汇总的总销售额,但只保留总销售额超过 50,000 美元的地区。”
这个提示会强迫你依次使用 SELECT、FROM、GROUP BY、HAVING 和 SUM 聚合。把查询写出来。大声读一遍。然后稍微改一下题目——换一个不同的阈值,再加上 ORDER BY 来给地区排名。目标不是写出完美 SQL,而是让你习惯在各个子句之间切换而不至于卡住。
面试前最后 10 分钟该重点练什么?
切换到 joins 和一个子查询。提示:“你有通过 `customer_id` 关联的 `customers` 和 `orders` 两张表。写一个查询,返回所有客户,包括那些从未下过单的客户。” 这会强迫你选择 LEFT JOIN。然后再来一句:“找出下单最多的客户。” 这可以用子查询解决,也可以用 JOIN 加 ORDER BY 和 LIMIT——两种都试一下。
每写完一个查询,就用一句话把答案说出来:“我这里用了 LEFT JOIN,因为即使客户没有匹配订单,我也要保留他们。” 这种口头总结正是面试官想听到的内容。对初学者进行入门级 SQL 筛选的反复辅导显示出同样的模式:能写出查询但说不清楚的人,后续会被追问得更紧;而先解释再写查询的人,往往能更快通过。
接下来通常会被追问什么
回答完一个基础 SQL 问题后,你通常应该预期哪些追问?
面试官在基础 SQL 答案后的标准动作,是测试你到底是背下来的,还是真的理解了。如果你解释了 GROUP BY,他们会问:“如果你 SELECT 一个不在 GROUP BY 里的列会怎样?”(不同方言下,SQL 会报错,或者返回不确定的值。)如果你解释了 INNER JOIN,他们会问:“如果右边有多行匹配会怎样?”(左边会出现重复行——每个匹配结果一行。)
在常规筛选轮里,常见的追问包括:“你能用查询演示一下吗?”、“如果这里有 NULL 会怎样?”、“你为什么选这个方案而不是子查询?” 规律始终一样:在你刚刚给出的定义之上,再深入一层。
如果让你当场写查询,该怎么回答?
说对话和现场搭建查询是两种不同的能力。被要求现场写的时候,请边写边讲:“我先写 SELECT 和需要的列,然后用 FROM 指明表,再加 WHERE 在分组前过滤。” 这种实时解说有两个作用——它展示了你的思路,也给你争取了几秒钟思考时间,不至于沉默。
你现在就可以在纸上练的题目是:“你有一张 `employees` 表,包含 `name`、`department` 和 `salary`。写一个查询,按部门求平均工资,但只针对员工数超过 5 人的部门。” 在不查资料的情况下把它写出来。如果卡住了,就把你想做的事情说出来——面试官通常会在你思路正确时给一点提示。
如果你只会一种 SQL 方言,该怎么处理?
直接说,不要道歉:“我主要使用的是 PostgreSQL,所以我会按这个语法来写查询——但如果有方言相关的部分,我也可以指出来。” 这是一个干净、专业的回答。它比你在不确定差异的情况下硬写 MySQL 语法要好得多,后者很可能在面试官问到具体函数时露怯。
初级阶段真正的方言差异其实很小——比如行数限制时的 LIMIT 和 TOP,一些字符串函数的差异,以及少数 NULL 处理边缘情况。根据 W3Schools 的 SQL 参考,核心 DML 语法(SELECT、WHERE、JOIN、GROUP BY)在 MySQL、PostgreSQL 和 SQL Server 之间足够一致,因此初学者在任何一种方言里给出的答案通常都能被正确理解。比起方言不熟,更大的风险是夸大自己只略微看过的方言能力。
Verve AI 如何帮助你在 SQL 编程面试中表现更好
SQL 面试准备最难的部分不是学语法,而是在现场写查询时,能在压力之下、一边有人盯着的时候,把思路清晰地解释出来。知道答案和流利说出答案之间的那道鸿沟,正是 Verve AI Interview Copilot 试图弥补的。
Verve AI Interview Copilot 会 实时读取你的屏幕——无论你是在 HackerRank、LeetCode、CodeSignal 上做 SQL 题,还是在实时技术面试中——并根据你屏幕上真正显示的内容给出建议,而不是泛泛的提示。如果你正在写查询,却一时想不起来该用 HAVING 还是 WHERE,Verve AI Interview Copilot 可以在你陷入沉默、气氛开始尴尬之前,及时给出区别。Secondary Copilot 功能会帮你一次只专注于一个问题,而不是在压力上升时把注意力发散到别的主题。并且由于桌面应用在系统层面不会被屏幕共享看到,支持内容只在你和屏幕之间保留。对于一个只准备了一个晚上的初学者来说,拥有一个能 根据眼前真实情况做出反应 的工具——而不是一套固定脚本——就是单靠死记硬背无法提供的结构性优势。
结论
你不需要在基础筛选面试之前掌握全部 SQL。你只需要掌握面试官反复问到的那几个要点——从 SELECT 到 HAVING、三种 key、LEFT JOIN 与 INNER JOIN 的选择,以及那些会悄悄破坏聚合答案的 NULL 陷阱。这是一组可管理的内容,而且完全可以在一个专注的晚上学会。
把这 30 分钟流程完整跑一遍。把查询写在纸上。把答案说出来。目标不是听起来像刚读过教科书,而是听起来像一个真正用过这些工具、也知道每个工具为什么存在的人。带着这一点走进去,基础就不会成为拦住你的东西。
Verve AI
内容
