资讯详情

SQLZOO中文版习题拆解:掌握SQL核心思维,告别死记硬背

📅 2026/9/13 21:11:22 | 华诺云谱 👁 阅读
SQLZOO中文版习题拆解:掌握SQL核心思维,告别死记硬背
很多学 SQL 的朋友都绕不过 SQLZOO 这个练习平台尤其是中文版出来之后入门门槛又低了一截。但我在带新人、逛论坛的过程中发现一个普遍问题很多人对着 SQLZOO 的题目能写出来却说不清为什么这么写换个场景就不会了还有人卡在某个关卡看了答案也看不懂最后只能死记硬背。这篇文章我就把 SQLZOO 中文版整套习题的思路好好拆一遍不是简单贴答案而是把每一类题背后的 SQL 逻辑、常见写法、容易踩的坑全部讲透让你做完这套题之后是真的会用 SQL而不是只会复制粘贴。SQLZOO 的中文版覆盖了从最基础的 SELECT 到 JOIN、子查询、聚合函数、窗口函数这些核心知识点题目设计得很讲究——它不会直接告诉你“用 GROUP BY”而是通过问题让你自己意识到“这里必须分组统计”。所以这套题的价值不只是刷题本身而是帮你建立用 SQL 解决问题的思维习惯。无论是刚接触数据库的大学生还是想转行数据分析的职场人又或者是写业务代码但 SQL 水平停留在 SELECT * 的开发者把 SQLZOO 刷透都是一笔回报率很高的投资。1. 整体设计与学习思路为什么 SQLZOO 值得刷1.1 平台结构与章节逻辑SQLZOO 的章节安排是循序渐进的我简单梳理一下SELECT basics基础查询WHERE、IN、BETWEEN 这些最底层的过滤逻辑SELECT from WORLD在真实国家数据上练手涉及比较运算、字符串匹配、数值处理SELECT from Nobel诺贝尔奖数据条件组合、IN 和 NOT IN 的进阶用法SELECT within SELECT子查询启蒙WHERE 里套 SELECTSUM and COUNT聚合函数、GROUP BY、HAVING统计分析的起点JOIN多表关联INNER JOIN 和 LEFT JOIN 的核心区别More JOIN巩固 JOIN引入演员和电影数据库关联条件更复杂Using Null处理空值COALESCE、CASE WHEN、IS NULL 的实战场景Self join自连接解决同一张表内部的数据关系问题这个设计思路非常有意思——它不是在教语法而是在模拟真实业务中会遇到的数据问题。“全世界的国家有哪些”是数据查询“每个大洲的国家数量”是数据统计“演员合作过几次”是数据关系。做完这套题你对 SQL 的认知会从“怎么写”升级到“怎么想”。1.2 刷题的正确姿势与常见误区我见过太多人刷 SQLZOO 的方式是卡住了就看答案看懂了就过然后发现下一题还是不会。这种方式效率极低因为答案只能告诉你“怎么实现”不能告诉你“为什么这么实现”。我的建议是每道题至少给自己 20 分钟的独立思考时间。如果卡住了先别急着看答案尝试把问题拆解——是过滤条件不清楚还是需要对数据进行分组还是需要关联另一张表把这个判断过程写下来哪怕最后没写对这个思考过程本身就有价值。另外一个常见误区是忽略数据本身。SQLZOO 的数据集都是真实数据比如国家表、诺贝尔奖表、电影演员表。做题前先花两分钟熟悉表结构看看都有哪些字段数据长什么样。很多题目的解题思路其实就藏在数据里。我在带新人时发现凡是先看数据再做题的人进度普遍比直接上手写 SQL 的人快得多。2. 核心章节解析与解题思路拆解2.1 SELECT basics 与 SELECT from WORLD基础中的基础第一个章节 SELECT basics 看着简单但它是后面所有章节的地基。这里涉及的 WHERE 条件过滤、IN 操作符、BETWEEN 范围筛选是 SQL 查询最核心的骨架。我记得有一道题是查找人口在 100 万到 200 万之间的国家很多新手会写成WHERE population 1000000 AND population 2000000这没问题但更简洁的写法是WHERE population BETWEEN 1000000 AND 2000000。能在最简单的地方养成简洁习惯后面复杂查询才不会写得拖泥带水。SELECT from WORLD 这章开始引入真实数据我重点讲几个高频考点第一是 LIKE 模糊匹配。题目里会出现“名字以 C 开头”“名字包含字母 a”这类需求。LIKE C%是开头匹配LIKE %a%是包含匹配LIKE _a%是第二个字符为 a。很多人在这一步容易混淆%和_的区别我记忆的方式是%代表任意多个字符包括零个_代表恰好一个字符。这个区分在后面的题目里会反复用到。第二是空值的处理。有一道题要查名字不为空的国家很多新手会直接写WHERE name ! NULL这绝对是错的。任何值和 NULL 做比较运算结果都是 NULL也就是不成立。正确写法是WHERE name IS NOT NULL。这个坑几乎每个学 SQL 的人都会踩一次我建议你把它刻在脑子里判断空值只能用 IS NULL 或 IS NOT NULL不能用 或 !。第三是数值处理函数。ROUND 函数在题目里经常出现比如把人口数四舍五入到百万位。这里的坑在于 ROUND 的第二个参数是小数位数正数表示小数点后保留几位负数表示整数部分从个位往左数几位。比如ROUND(1234567, -3)的结果是 1235000因为它把千位以下的数字都变成了 0然后四舍五入到千位。2.2 SELECT from Nobel多条件组合与优先级Nobel 这章的数据是诺贝尔奖得主名单字段包括年份、科目、获奖者姓名。这里的题目开始涉及多个条件的组合比如“1962 年的文学奖获得者”或者“爱因斯坦的所有获奖记录”。多条件组合的核心就是 AND 和 OR 的优先级问题。我遇到过一个经典问题查 1980 年物理奖或 1984 年化学奖的获得者。新手容易写成SELECT * FROM nobel WHERE yr 1980 AND subject Physics OR yr 1984 AND subject Chemistry;这个写法碰巧是对的因为 AND 的优先级高于 OR所以它会被解读为(yr 1980 AND subject Physics) OR (yr 1984 AND subject Chemistry)。但问题是一旦条件变多依赖优先级容易出错。比如要查“1980 年的物理奖或文学奖获得者”正确写法是SELECT * FROM nobel WHERE yr 1980 AND subject IN (Physics, Literature);我强调一下IN 在多个同字段条件判断时比一串 OR 清晰得多。而且 IN 后面还可以接子查询这个在后面章节威力更大。这章还有一个经典题目是排除特定科目比如查除了哲学和经济学之外的所有获奖记录。这里有个很隐蔽的坑获奖者的名字可能为 NULL。如果你写WHERE subject NOT IN (Philosophy, Economics)而且 subject 字段里恰好有 NULL 值你会发现有些记录莫名奇妙地消失了。原因还是 NULL 的坑——NULL NOT IN (列表)的结果是 UNKNOWNWHERE 只保留条件为 TRUE 的行UNKNOWN 会被过滤掉。这个题我在实战中帮别人排查过很多次每次都能发现有人在这种细节上翻车。2.3 SELECT within SELECT子查询的三种典型场景子查询是很多人的分水岭学明白了后面的聚合函数和 JOIN 都轻松。SQLZOO 这章的题目设计得很巧妙我归纳为三种典型场景第一种是 WHERE 子查询也是最常见的。题目类似“找出人口超过俄罗斯的国家”。你先把俄罗斯的人口查出来再把它嵌到外层查询里SELECT name FROM world WHERE population (SELECT population FROM world WHERE name Russia);子查询先执行把结果返回给外层查询使用。这种单值子查询也叫标量子查询是入门基础。第二种是 IN 子查询子查询返回一列值。比如“找出和 Turkey、Poland 同一大洲的国家”。注意关键字 ALL 和 ANY 的使用——WHERE population ALL (子查询)表示大于子查询返回的每一个值WHERE population ANY (子查询)表示大于子查询返回的任意一个值。区别很微妙但题目里一定会用到理解了 ALL 和 ANY 的逻辑会让你的 SQL 水平上一个台阶。第三种是 FROM 子查询把子查询的结果当成一张临时表来用。比如“找出每个大洲人口最多的国家”。这类题用 JOIN 也能做但 FROM 子查询在某些场景下性能更好。SQLZOO 里的官方解法通常用的是关联子查询我的评价是能写对就行但理解 FROM 子查询能让你的思路更开阔。子查询这块我的建议是动笔把每个例子都跑一遍然后试着用不同的写法去解同一道题对比结果是否一致。这个过程能帮你打通关节真正理解 SQL 的执行顺序。2.4 SUM and COUNT GROUP BY 与 HAVING 的精髓这章的题目像“每个大洲有多少个国家”“每个大洲的人口总和”这类统计问题核心是聚合函数和分组。COUNT、SUM、AVG、MAX、MIN 这五个聚合函数必须熟练掌握而 GROUP BY 则是把数据按某个字段分组然后对每一组做聚合计算。举个例子题目要求“统计每个大洲的国家数量”写法是SELECT continent, COUNT(name) FROM world GROUP BY continent;这里有个细节SELECT 里的非聚合字段必须出现在 GROUP BY 中。上面的continent在 SELECT 里出现同时也在 GROUP BY 里这是合法的。如果你写成SELECT name, COUNT(continent) FROM world GROUP BY continent大多数数据库会直接报错因为 name 没有包含在 GROUP BY 子句中。这个规则不搞清楚后面写复杂查询时会一直报错。HAVING 是这章另一个重点。WHERE 是在分组之前过滤行HAVING 是在分组之后过滤组。比如“找出国家数量超过 5 个的大洲”SELECT continent, COUNT(name) FROM world GROUP BY continent HAVING COUNT(name) 5;我见过有人想当然地用WHERE COUNT(name) 5结果报错。WHERE 不能使用聚合函数作为过滤条件因为聚合函数是在分组阶段才计算的而 WHERE 在分组之前就已经执行完毕了。记住这个执行顺序能避免很多低级错误FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY。2.5 JOIN 与 More JOIN多表关联的核心思维JOIN 是 SQL 里最实用的部分也是实战中运用最多的。SQLZOO 这章用的是球员进球数据分两张表game比赛和 goal进球记录。像“查询每场比赛的比分”“查询每场比赛的所有进球球员”这类题核心就是搞清楚表之间的关联字段。INNER JOIN 和 LEFT JOIN 的区别是这章的重点几乎每道题都在强化这个概念。INNER JOIN 只返回两表中匹配上的行LEFT JOIN 返回左表的全部行右表没有匹配的用 NULL 填充。在实际业务里这个区别极其重要——你统计每个部门的员工数量如果用 INNER JOIN会漏掉没有员工的部门如果用 LEFT JOIN就能把这些部门也统计出来然后通过 WHERE 条件筛掉 NULL。More JOIN 这章用的是演员电影数据库movie、actor、casting关联条件更复杂需要三表关联。思路是先用 JOIN 把 movie 和 casting 关联再和 actor 关联。这类题的难点在于关联条件的选择。多表 JOIN 时我建议先画一个简单的关联图搞清楚到底哪张表和哪张表通过什么字段关联然后再动手写 SQL。直接上手写代码大概率会在关联条件上迷失方向。3. 实操过程与核心技能详解3.1 Using Null处理空值的完整方案Using Null 这章是对空值处理的集中练习。数据表中有经理字段可能为 NULL表示该员工没有经理或者是一个顶级领导。这一章的题目让我印象非常深刻因为空值处理是实际工作中绝对绕不开的坎。COALESCE函数是这章的主角它接受多个参数返回第一个非 NULL 的值。比如COALESCE(manager, BOSS)如果 manager 是 NULL就显示 BOSS。还有CASE WHEN表达式这是 SQL 里最灵活的语法之一。比如“查询员工姓名如果有经理就显示经理姓名没有就显示 BOSS”SELECT name, CASE WHEN manager IS NULL THEN BOSS ELSE manager END FROM employee;CASE WHEN 就是一个 if-else 的 SQL 版本可以嵌套使用也可以配合聚合函数做条件统计。SQLZOO 的题目设计得很贴心它不会直接说“请用 CASE WHEN”但当你发现没法用简单的 WHERE 和聚合解决问题时就会自然想到它。这种设计逼迫你跳出舒适区去掌握更高级的语法。3.2 Self join一张表的自关联艺术Self join 是 SQLZOO 的压轴章节也是很多人觉得最抽象的部分。它其实没那么神秘——就是同一张表自己和自己 JOIN。难点在于理解“为什么需要自连接”。自连接的典型场景是一张表的某一行需要和同一张表的另一行做比较。比如员工表里每个员工有 manager_id 指向另一个员工你如果想查“每个员工的上级叫什么名字”就需要把员工表自己和自己关联一次当员工表用一次当经理表用SELECT e1.name, e2.name AS boss_name FROM emp e1 JOIN emp e2 ON e1.manager_id e2.id;在这里e1 和 e2 是同一个表但你把它当作两张独立的表来看待。SQLZOO 的 Self join 章节用的是公交线路数据要查“哪些站点可以换乘”本质上就是找同一线路上的不同站点组合。需要给表起别名否则 SQL 根本分不清到底引用的是哪一份数据。自连接的核心思维是“同一张表里的数据如果存在层级或对应关系就可以通过自连接把一对多的关系变成单表查询。”掌握了这个思维后面处理组织机构、分类层级、好友关系这类数据时会轻松很多。3.3 窗口函数从 SQLZOO 延伸出去的进阶技能SQLZOO 主体章节没有专门的窗口函数练习但是它在 More JOIN 之后的章节里有一道类似“排名”的题目会用窗口计数。实际上窗口函数是 SQL 进阶路上无法回避的内容ROW_NUMBER()、RANK()、DENSE_RANK()和SUM() OVER(PARTITION BY ...)在数据分析场景中是绝对高频的写法。举个 SQLZOO 的相似例子如果我们要按大洲分组给每个大洲内的国家按人口排名窗口函数就是为此而生的SELECT name, continent, population, RANK() OVER(PARTITION BY continent ORDER BY population DESC) AS rank_in_continent FROM world;PARTITION BY continent把数据按大洲分组ORDER BY population DESC为每个分组内的国家排序RANK()则为每个组生成排名。秒杀一切用自连接或子查询模拟排名的方案。虽然 SQLZOO 不强制要求窗口函数但我强烈建议你做完基础题目后把窗口函数作为下一个学习目标——它在实际工作中的价值极高几乎每一个 SQL 面试都会涉及。3.4 SQL 规范和可读性建议SQLZOO 的题目基本不需要写超长代码但养成良好书写习惯仍然重要。我的个人风格是关键字用大写SELECT、FROM、WHERE、GROUP BY 这些统一用大写字段名和表名用小写。这能显著提高可读性。子查询缩进子查询内部语句整体缩进四格一眼就能看出嵌套关系。逗号放在字段名前面这在字段很多时特别有用方便逐行检查哪个字段漏了。SQL 写出来不仅是给数据库执行的也是写给人看的。你过两周再回来看自己的代码能一眼看明白这才是好代码。SQLZOO 的习题量刚好够你养成这些习惯别浪费了。4. 常见问题与排查技巧实录4.1 SQLZOO 中文版的特殊坑点SQLZOO 中文版整体翻译质量不错但有几个地方容易让人误解第一“Show the name and population for France, Germany, Italy”这类题目中文翻译成“显示出法国、德国、意大利的名称和人口”用 IN 一次性查询更简洁。但新手容易一个一个 OR 写很笨拙。第二某些题目里字段名有大小写差异。SQLZOO 的表名字段名在 MySQL、PostgreSQL、SQL Server 里表现不同如果你的本地环境是 Linux 上的 PostgreSQL字段名大小写敏感会造成查询报错。我的建议是严格按照题目给定的字段名来写不要自己改大小写。第三题的通过判定有时比较死板。SQLZOO 的判定只看返回的数据是否和预期一致不看你的 SQL 写法。比如“列出每个大洲和每个大洲的国家数量”写COUNT(*)和COUNT(name)得到结果一样但有些本地数据库对 COUNT 的处理不同导致结果数值略有差异。如果本地跑的结果和平台不一致优先检查题目里是否要求了 COUNT 具体的字段。4.2 报错信息解读快速定位问题调试 SQL 时最常见的报错信息就那几类我总结成速查表报错信息含义常见原因Unknown column xxx字段不存在拼写错误或表里根本没有这个字段Column xxx not in GROUP BY字段不在分组中SELECT 的字段必须要么是聚合函数要么在 GROUP BY 中Invalid use of group function聚合函数使用不当WHERE 里用了 COUNT、SUM 等聚合函数You cant specify target table for update in FROM clause更新时不能查询同表需要包一层子查询或使用多表 UPDATEUnknown table xxx表不存在表名拼写错误或没有选中对应数据库排查问题不要瞎试先看报错信息定位到具体是哪一行再看是语法问题还是逻辑问题。我调试 SQL 的经验是先解决语法层面的报错再检查逻辑层面是否满足需求。语法错误不解决讨论逻辑没有意义。4.3 为什么你的结果和答案对不上这种问题几乎每个人都有过——明明 SQL 能跑通返回的结果就是和答案不一致。我总结了一下主要原因有几类第一类是边界条件。比如题目说“人口超过 100 万”你需要自己判断到底是大于 100 万还是大于等于 100 万。SQLZOO 的题目表述通常是比较明确的但偶尔存在模棱两可。我的建议是做题时先看清楚题目要求然后用平台自带的数据检查一下看边界条件是否符合预期。第二类是 NULL 值处理不一致。比如 COUNT 一个字段字段中含有 NULL 值COUNT(*)会把包含 NULL 的行也数进去而COUNT(字段名)只数非 NULL 的行。如果题目没有明确要求两种写法的结果可能不同。在写 GROUP BY 统计时明确你统计的对象是什么可以避免这种问题。第三类是排序导致的结果顺序不同。SQLZOO 平台判定结果时通常不看顺序但用户自己对比时容易误判。如果返回的数据内容一致只是顺序不同别慌加个 ORDER BY 再对比就好了。5. 刷题之外的实战心得与扩展建议SQLZOO 刷完之后千万不要停下来。它帮你搭好了 SQL 的地基但离真正的实战还有一段距离。根据我个人经验接下来你可以往这几个方向扩展第一个方向是在真实数据库上练习。SQLZOO 的在线环境为了简化屏蔽了索引、性能这些概念但在生产环境中 SQL 的性能优化是重中之重。慢 SQL 优化是一个永恒的话题核心思路是先用EXPLAIN看执行计划确认走没走索引再看能不能用改写 SQL 的方式减少扫描行数。这个方向推荐作为 SQLZOO 之后的学习目标。第二个方向是结合业务场景做项目。SQLZOO 的练习都是单表或两三张表的小场景真实业务动辄十几张表关联。我建议你找一个开源的数据集比如电影评分数据、电商订单数据自己设计一些分析题目然后用 SQL 去实现。这个过程里你一定会遇到 SQLZOO 里没有的坑而解决这些坑的过程就是真正的成长。第三个方向是把 SQL 和你的主语言结合起来。如果你是 Java、Python、Go 开发者学习如何在代码中安全地拼接 SQL、如何使用参数化查询防止 SQL 注入是必须要补的一课。SQL 注入是 Web 安全领域最常见的漏洞之一本质就是字符串拼接导致 SQL 结构被篡改。理解了 SQL 的执行逻辑你自然就能理解为什么参数化查询是最重要的防线。再分享一个小技巧。SQLZOO 刷题时我给自己定了个规矩每道题至少用两种写法实现然后对比两种写法的结果和性能。比如 JOIN 和子查询IN 和 EXISTSGROUP BY 和窗口函数。这个过程会逼着你去理解不同 SQL 写法之间的优劣而不是仅仅停留在“能跑就行”。说实话SQLZOO 的价值从来不是那几十道题的答案而是在解题过程中建立的对数据关系的直觉。有了这个直觉你面对一张从未见过的表也能快速判断出该用什么查询、该怎么组合数据。这个是刷题最大的回报。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。