“MySQL SQL100道基础练习题”这名字听起来平平无奇甚至有点像是网盘里随手存下来的旧资料但真正把它从头到尾刷完一轮之后我才意识到它可能是SQL入门阶段性价比最高的一份学习材料。没基础的人拿到这套题最容易犯两个错一是觉得题目太简单跳着做做完像没做二是卡在两三题之后就没了耐心转头开始翻答案。无论哪种最后都会得到同一个结果——合上题库脑子里只剩“我好像学过SQL”但手上一句完整查询都写不出来。这套练习能解决的核心问题其实就一句话把你脑子里的“语法印象”变成手上能直接输出的“查询能力”。它适合三类人刚学完SELECT、JOIN等基本语法、正愁没有系统训练的新手面试前想快速找回手感的数据分析岗位候选人以及写业务代码时总在简单查询上卡壳、需要补基础的后端开发者。如果你属于其中任何一类这套题都值得认真过一遍。1. 先理清楚这套题到底在练什么1.1 100道题的结构比例不是随便定的市面上常见的MySQL基础练习题库虽然具体题目各有不同但结构高度统一单表查询、多表查询、聚合分组、子查询、增删改、建表与约束。100道题里查询类题目通常能占到六到七成DML增删改大概十五题左右DDL建表、约束、索引十题上下剩下才是综合题。这个比例不是出题人拍脑袋定的它对应的是真实的业务使用频率。日常工作中你和数据库打交道95%的时间都在做查询取数而不是在改表结构。面试里手写SQL考的基本也是查询。所以题库把大头压在查询上本质是在逼你优先把最常用的技能练透。很多人一上来就盯着窗口函数、复杂SQL技巧看结果连WHERE和GROUP BY的执行先后都说不清楚这就是本末倒置了。1.2 基础题为什么值得反复刷我见过不少写了两年业务代码的开发者一说SQL优化头头是道真让他写一条“查每个分类下销量前3的商品”反而会先写出一版带多个子查询的慢SQL然后慢慢调。问题不在技巧不够而在基础查询的熟练度不够脑子里的SQL模板太少遇到需求只能现场拼装拼出来还不一定对。刷基础题的意义有点像运动员练基本功。职业球员不会因为会扣篮就不练传球SQL也一样它要练到WHERE、GROUP BY、ORDER BY这些语法像条件反射一样输出不需要停下来想“子句顺序是什么”的程度。这套100题的价值就是让你在低压力、高重复度的环境里把这些语法点焊死在肌肉记忆里。提示刷题时尽量别用图形化工具里那种“拖字段”的方式拼查询老老实实手写SQL写不出来的才去查、去问这比看一百遍教程都管用。2. 核心考点拆解每一类题背后的出题意图2.1 建库建表与约束先把“房子”搭对基础题一般会从建库建表开始给你一个“学生-课程-成绩”类的小型业务模型让你把三张表建出来带上主键、外键、非空、默认值等约束。这一部分题目的出题意图不是真的让你去设计一套生产库表结构而是让你理解两个底层逻辑第一数据必须按结构落盘先有表才有数据第二表与表之间靠什么建立关系。实际操作里最容易出错的地方是联合主键。比如成绩表通常由学生ID和课程ID共同决定唯一记录那主键就应该是PRIMARY KEY (student_id, course_id)而不是单独给成绩表加一个自增ID。很多新手会误以为每张表都必须有一个id字段这个认知在练习阶段就该被纠正。另一个经典考点是外键约束。练习里建表时加上外键目的不是让你在正式项目里滥用外键高并发业务里很多人会刻意去掉物理外键而是让你理解“引用关系”这个概念。这样学到JOIN时你才能明白两张表是靠什么字段连起来的。2.2 单表查询占比最大最容易被小看单表查询的题目类型非常固定条件过滤WHERE、去重DISTINCT、模糊匹配LIKE、范围过滤BETWEEN、排序ORDER BY、限制返回行数LIMIT以及它们之间的组合。这类题看着简单几个常用错误却高频出现。一是条件里的字符串不加引号数字和字符串的隐式转换导致结果诡异二是写LIKE时忘了%的语义好多人想查“以某字符结尾”的数据结果用了LIKE 某字符%方向直接反了三是排序字段搞混ORDER BY从上到下依次是主排序、次排序很多人只写一个字段达不到题目的排序要求。单表查询里还有一个容易被忽略的知识点NULL的过滤。用 NULL查不到任何数据必须用IS NULL或IS NOT NULL。很多人在这一步第一次意识到“NULL不是值是一个状态”这个理解会影响后面所有的聚合和多表查询基础题在这里反复出题不是在刁难人是在帮你提前排雷。2.3 聚合与分组所有“平均数”题的共同套路聚合是这套题的分水岭也是新手第一次大面积卡壳的地方。题目一般长这样查每门课程的平均分、查每个学生的总成绩、查选课人数超过X的课程。它们的本质都是同一个动作——“按某个维度分堆再对每一堆做计算”。这里必须搞清楚三件事分组维度、聚合函数、过滤位置。分组维度决定结果的行数比如按课程分组一门课就是一行聚合函数决定每行显示什么AVG(score)、SUM(score)、COUNT(student_id)各自算的是哪一列过滤位置则是个经典考点——对分组前的数据过滤用WHERE对分组后的结果过滤用HAVING。拿题目“查询平均分大于60分的课程”来说正确写法是先用GROUP BY course_id按课程分组再用HAVING AVG(score) 60过滤。如果你写成WHERE AVG(score) 60直接报错因为WHERE在执行顺序上先于聚合它压根不知道AVG是什么东西。这个执行顺序问题我把话放这儿100道题里至少可以帮你踩中三次。2.4 连接与子查询多表场景的两种思维多表查询题目核心就两个套路JOIN连接和子查询。连接题考察的是连接类型的选择——内连接取交集左连接保留左表全部记录右连接反之子查询题则考察“能不能先把问题拆成两步”。比如经典题“查出没有选过任何课程的学生的名单”两种写法都可以一种是LEFT JOIN课程表再WHERE课程字段为NULL另一种是NOT EXISTS子查询。前者是“连完再过滤”的集合思维后者是“逐行判断”的逐行思维。这两种写法在练习里都应该写一遍因为它们的性能差异在不同数据量下会被放大练的就是一眼看穿“这道题适合用哪种”。新手最容易栽在多表查询的两个位置一是JOIN时忘记写连接条件产生笛卡尔积两表各100条数据结果直接变成10000行还看不出哪里不对二是子查询的嵌套层次写得过深三层四层套下去一报错就不知道错在哪个括号里。基础题里虽然也有多层子查询但我建议你先练到“两层子查询能稳定写对”的程度就足够应付九十道题了。3. 实际刷题一套能落地的练习流程3.1 环境准备有图形工具也要有命令行刷题之前先把环境准备好。MySQL版本建议8.0以上因为它对窗口函数、公用表表达式的支持比较完整万一后面想往进阶方向练不用换环境。本机装MySQL再搭配一个客户端就行这里我不推荐具体工具你习惯哪个用哪个。但有一点即使你平时习惯了图形界面练习阶段也建议把MySQL自带的mysql命令行用起来。原因很简单面试手写SQL用的是文本不是拖拽早点习惯纯文本环境考试和面试时会更从容。数据准备这块网上有很多现成的学生选课示例数据可以直接导入。如果没有自己手搓个几十条数据也行重点是表结构别太随意。我自己的习惯是建三张表student存储学生信息course存储课程信息score存储选课成绩三张表通过ID字段互相引用。这套小模型几乎能覆盖100道题里的所有场景练完再换业务型数据思路是通用的。3.2 刷题节奏别想着一天刷完100道题不建议一口气刷完人的专注力撑不住而且后面几道题和前面是强关联的前面积累不牢后面会越做越挫败。我的建议是分四到五天每天安排二十到三十道按题型分组练第一天集中做建表和单表查询第二天专攻聚合与分组第三天练连接和子查询第四天做增删改和综合题第五天把所有错题重做一遍。每次练习控制在三十到四十五分钟别拉太长。刷题过程中把每道题的耗时记下来一道单表查询超过五分钟还没思路就说明对应知识点有缺口别硬扛回头翻翻基础概念再来。这里有个微小但重要的习惯每写完一条SQL先自己判断“大概率对”再执行看结果而不是先执行、错了再改。这个习惯能让你逐渐培养出“读SQL就能预判结果”的能力这是区分熟手和新手的一个明显标志。3.3 两个典型题目拆给你看挑两道比较有代表性的题目演示一下从读题到验证的完整路径。第一道是“查询每门课程的平均分并按平均分降序排序”。先拆题要的是“每门课程”说明分组维度是课程ID要的是“平均分”说明要用AVG(score)要“降序排序”说明要用ORDER BY。组合起来的写法SELECT course_id, AVG(score) AS avg_score FROM score GROUP BY course_id ORDER BY avg_score DESC;这里注意ORDER BY可以直接引用avg_score这个别名因为它在聚合之后执行。很多新手在这里会再写一遍AVG(score)排序虽然没错但没必要。执行后如果你看到的结果和题目预期对不上优先检查的是GROUP BY的字段是不是课程ID而不是学生ID。第二道是“查出没有选过任何课程的学生的姓名”。这道题看是查学生信息实际上“没选过课”这个条件得靠另一张表来判断。用子查询的写法SELECT student_name FROM student WHERE student_id NOT IN ( SELECT student_id FROM score );用连接也能写SELECT s.student_name FROM student s LEFT JOIN score sc ON s.student_id sc.student_id WHERE sc.student_id IS NULL;两种写法结果一样但思路不同。第一种是先查“所有选过课的人”再反选出“没选过课的人”第二种是“把学生左连接成绩表没匹配上的就是没选过课的人”。练这种题的时候建议同一道题逼自己用两种方法写一遍这是培养SQL思维多角度能力最便宜的方式。3.4 写完SQL之后四个自查点执行通过不代表题目做对了我自己刷题和带人刷题时都会留一个固定动作自查。每道题写完先别急着看结果按四个点检查一遍。第一结果行数是否符合直觉。比如“每个学生的总成绩”结果行数应该和总人数一致如果多出几行多半是分组维度错了或者有重复数据。第二分组粒度是否正确。这一点多表查询时尤其容易乱查“每门课的平均分”时脑子里要清楚结果是一行一门课不是一行一个学生。第三NULL有没有漏掉。凡是题目里出现“没有”“未”“不含”这些字眼都要优先考虑NULL参与判断的场景。第四有没有多余的全表扫描。练到后面可以顺手在查询前面加一个EXPLAIN看看是不是走了全表扫描如果是顺便想想能不能靠加索引解决。这一步不是超纲是提前让你习惯“不是查出来就完事”的工程思维。4. 刷题过程中最常见的错误与排查清单4.1 语法坑最气人的往往是最后多了一个逗号SQL语法报错的问题90%都集中在几个非常低级的位置。手写SQL时最常见的就是逗号问题SELECT的字段列表、INSERT的值列表、GROUP BY后面的字段列表最后一个字段后面多写了一个逗号数据库直接报语法错误。你盯着屏幕看半天怎么看怎么对其实就是多了一个逗号。另一个高频问题是用错引号。SQL里字符串字面量用单引号字段名、表名用反引号MySQL里有些新手把字段名也用双引号包起来在默认SQL模式下会报错或者行为怪异。还有一个容易被忽略的坑是SQL语句结尾的分号在命令行里如果忘了加分号回车之后不仅不执行还会进入续行状态新手经常会误以为命令卡死了。这类语法错误在排查时别慌先看报错位置提示MySQL的报错信息会指向具体位置。根据我实际的观察新手犯错最密集的就是字段顺序错误、别名写错、子查询少了括号这三个位置建议平时写完就养成分段执行的习惯先把子查询单独跑一遍再跑整个查询错误会好找很多。4.2 逻辑坑结果不对八成是分组和连接出了问题语法全对结果却跟答案对不上这种问题最折磨人。这类逻辑坑最常见的就两个一是把聚合条件的过滤位置放错二是JOIN没有加上正确的关联条件。前者我在前面提过WHERE负责过滤分组前的行HAVING负责过滤分组后的结果。比如“查平均分大于80的学生”如果条件写在WHERE AVG(score) 80里数据库直接报错如果条件里混进了非聚合字段比如HAVING student_name 小王结果看起来也是对的但放在这里其实并不合理——单条记录的字段应该在WHERE里过滤否则分组后再过滤逻辑上已经说不通了。后者更隐蔽。两表连接时如果漏写ON条件或者ON条件写错字段结果不会报错但行数会暴涨一旦结果行数离谱优先怀疑笛卡尔积。还有一种情况是JOIN方向选错比如题目要“显示所有学生及他们的选课情况”如果用了RIGHT JOIN没选课的学生就被过滤掉了看半天也找不到原因。这种错误只能靠经验积累但你可以通过一个动作减少出错概率动手连接之前先在注释里写清楚“以哪张表为基准、希望保留哪些行”再写SQL。4.3 心态坑别让“看答案”毁了这套题刷题时有一类问题跟技术无关但比技术问题更致命就是“答案依赖症”。很多新人五分钟想不出来手就不自觉地点开答案看完恍然大悟然后觉得自己会了实际关上答案再写还是写不出来。这种假性学习会给你一种“我刷了一百道题”的错觉实际上做题能力没有任何提升。我的建议是定一个规则一道题至少独立思考十五分钟写不出来可以翻语法笔记但不要直接看答案宁可先把题放下隔天再回来重做。另外错题不要当场改完就丢一定要在隔两天后重做一遍能独立重做出来才算真正吸收。这套100题如果每一道都是你自己想出来的即使只做了70道效果也比连看带抄刷完100道要好得多。为了排查方便我把刷题过程中最常踩的坑整理成一张速查表供你对照自查错误类型典型现象主要原因排查思路语法错误报错提示在结尾附近字段列表末尾多逗号检查SELECT、INSERT、GROUP BY最后一项语法错误字符串查询结果异常引号用错字符串用单引号字段名不用引号逻辑错误结果行数爆炸JOIN漏写ON条件补全连接条件检查是否形成笛卡尔积逻辑错误聚合条件报错WHERE里写了聚合函数聚合过滤改为HAVING逻辑错误NULL条件查不到数据用了 NULL改为 IS NULL / IS NOT NULL逻辑错误分组结果行数不对分组字段选错确认GROUP BY的列就是题目要求的维度习惯问题同一道题只会一种写法只练了JOIN或子查询其一同一题至少写两遍换一种思路4.4 一个被很多人忽视的坑字段名和保留字撞车基础题的数据表里偶尔会有字段名命中和SQL保留字重名的情况比如字段名叫order、group、key这类名字直接放在SQL里会报语法错误解决方法是加反引号包裹order。很多新手会在这里卡很久以为是SQL写错了其实是表结构设计时埋的坑。这个点我特意单独拿出来说是因为它虽然简单但一旦遇到很容易让人自我怀疑到怀疑人生。5. 练完这100题之后路可以怎么走5.1 错题复盘比刷新题更重要刷完100题你的错题就是最宝贵的资料。建议建一个简单的复盘表按题型分类记录比如“单表查询-排序”“多表连接-左连接”“聚合-HAVING”这样每道错题记两列当时的错误写法、正确的思路。这个动作听着土但能让你在两周之后快速定位自己的弱项而不是从头翻一遍题库。我当时带新人时发现一个规律一个人真正容易错的题型通常只有两三类绝大多数人在聚合与分组、多表连接两个模块反复出错。找到弱项之后不需要急着刷下一套题先把错题本上的类型重做三遍效果远胜于继续刷新题。5.2 进阶方向索引、执行计划、窗口函数100道基础题打完底你的SQL已经算入门了这时候再往高阶走方向就很明确了。首先是索引。基础题练习时基本只需要关心查询结果对不对但真实场景里SQL的性能往往比结果重要。下一阶段可以学习聚集索引和非聚集索引的区别理解为什么WHERE条件里对索引列做函数运算会导致索引失效。这是从“会写SQL”到“写好SQL”最关键的一步。其次是执行计划。EXPLAIN关键字在练习阶段只是偶尔看一眼进阶阶段就要认真读每一行的type、key、rows这些字段了。看到ALL就要意识到是全表扫描看到range说明索引范围扫描逐步建立“读写一条SQL就能大致预估性能”的能力。然后是窗口函数。MySQL 8.0开始支持ROW_NUMBER()、RANK()、DENSE_RANK()这类窗口函数它们能解决很多“分组内排名”的问题。基础题里不少需要用复杂子查询才能实现的题目如果放到窗口函数场景下会变得非常简单。这个知识点可以放在基础题刷完两周后再学把100题里的“查询每个分类下最高的那一条记录”用窗口函数再写一遍你会明显感觉到SQL的另一种打开方式。练完这100题后我个人的一个建议是别急着囤下一套题先把这套题里所有做错的、卡壳的题原题重做一遍。第二次做的速度如果明显比第一次快而且能写出两种解法说明这套题真的吸收进去了。如果有些题还是要想很久那就说明当初“看答案看懂了”其实是错觉现在发现还来得及补。最后再分享一个小习惯平时在业务里遇到磕磕绊绊的查询哪怕最后解决了也顺手把它记下来攒一段时间你会发现真实业务题比题库更复杂但思路基本都是从这100道基础题里长出来的。