简介这是一份针对数据库初学者的SQL语句练习题及答案文档适用于正在学习数据库原理、准备期末上机考试或求职面试的读者。资源以学生选课为典型业务场景围绕学生表、课程表、选课表三张表展开系统覆盖建库建表、插入与删除、更新数据、条件查询、聚合统计、多表连接、嵌套子查询等常见题型并逐题给出参考答案方便对照练习、查漏补缺。压缩包内为一个Word格式文档单文件约四十三KB题目按练习模块归类题量充足打开即可直接使用。目前已有五百二十人浏览学习既适合学生自主刷题巩固也可作为教师布置作业的现成题库。通过这套题目读者可以快速熟悉查询、更新、删除等核心语句还能掌握统计、分组、连接与子查询等高频考点的实际写法。1. 这份“sql语句练习题及答案.doc”到底值不值得花一个晚上去啃我见过太多人面试前一天拿着这种 doc 猛刷刷完觉得 SQL 稳了真到写题的时候连GROUP BY和HAVING的先后顺序都搞反。这类文档的最大价值不是让你背答案而是让你意识到“会读 SQL”和“会写 SQL”之间隔着一整条训练链。如果你正准备数据库面试、计算机二级、或者刚接手要写报表的活这份练习文档真正能帮你的是把语法点转成手速把错误转成经验。但前提是你会用而不是“看过”。很多人看了几十道题上机还是卡在ON和WHERE的过滤时机上——因为题是静态的数据是动态的。这篇笔记就把这份 doc 背后的练习体系拆开题目怎么排布、答案怎么核对、坑在哪、怎么把它练成真本事。读完你可以直接照着搭一套自己的 SQL 练习流程而不是对着一份答案抄到天亮。2. 题目怎么排布先看这套练习覆盖了哪些必考技能点拿到一份 doc先不要急着翻到答案页。第一件事是看它的目录和题目清单判断它到底是“按语法点分类”还是“随便堆了 50 道题”。有经验的练习材料一定是有结构的分层基础语法层、单表逻辑层、多表关联层、聚合与分组层、窗口函数层。如果你的这份 doc 没有这种分层后面做题时你会很痛苦——因为你会在 JOIN 题里被去重问题卡住在聚合题里被 NULL 坑到。2.1 一份能练出真功夫的练习题覆盖清单长什么样下面是我整理的一份“可抄作业”的技能点覆盖清单也是我判断一份题目质量高低的参照系。你可以打开你的 doc按这个表去对照缺哪块就补哪块技能层典型题目涉及的核心语法面试/考试出现频率基础查询查询表中所有字段、指定字段、字段别名SELECT/AS必考条件过滤查询分数大于80的学生名单WHERE/ 比较运算符 /LIKE必考排序与分页按成绩降序取前5名ORDER BY/TOP/LIMIT必考去重查询所有不重复的部门名称DISTINCT/GROUP BY高频聚合统计统计每个部门的平均工资、最高工资GROUP BY/HAVING/AVG/MAX必考多表关联查询员工姓名及其部门名称INNER JOIN/LEFT JOIN必考子查询查询工资高于平均工资的员工WHERE 子查询 /IN/EXISTS高频窗口函数查询每个部门工资排名前两名的员工ROW_NUMBER()/RANK()/PARTITION BY高频面试分水岭条件逻辑根据成绩划分优良中差CASE WHEN高频日期与字符串查询2023年入职的员工、拼接姓名YEAR()/CONCAT()/SUBSTRING()中频如果你的 doc 里这十类题都有那底子就算不错。如果只有前五类它对你的面试帮助会有限——现在的面试题无论大厂小厂窗口函数几乎成了标配去重逻辑也总是藏在业务题里。我一般会先用半天把这类技能点过一遍不看答案自己做一遍错了再翻答案标记下来。如果你发现自己 10 道 JOIN 题全对但窗口函数一题没写过就说明这份练习“广度”不足你得自己补充。2.2 拿到 doc 后先建一个能跑题的练习库大多数这类文档里只有 SQL 题和答案没有配套的建表语句。你必须在本地把“题目的数据环境”建起来否则你就是在“凭感觉看题”不是“验证自己对错”。我习惯用一个通用的“员工-部门-工资”练习库覆盖以上十类题建表语句如下-- 建部门表 CREATE TABLE dept ( dept_id INT PRIMARY KEY, dept_name VARCHAR(50) NOT NULL ); -- 建员工表外键关联部门表 CREATE TABLE emp ( emp_id INT PRIMARY KEY, emp_name VARCHAR(50) NOT NULL, dept_id INT, salary DECIMAL(10,2), hire_date DATE, region VARCHAR(20), FOREIGN KEY (dept_id) REFERENCES dept(dept_id) ); -- 插入示例数据 INSERT INTO dept VALUES (1, 技术部), (2, 市场部), (3, 销售部); INSERT INTO emp VALUES (1001, 张丽, 1, 12000.00, 2022-03-15, 华东), (1002, 王强, 1, 9500.00, 2023-07-01, 华北), (1003, 李芳, 2, 8800.00, 2021-11-20, 华东), (1004, 赵磊, 3, 15000.00, 2020-05-10, 华南), (1005, 孙悦, 3, NULL, 2023-01-12, 华北);为什么我会用这三张表和这五个字段首先dept_id做外键关联能练JOINsalary设为DECIMAL(10,2)是因为工资统计题一定会涉及聚合浮点类型会带来精度意外hire_date是练习日期函数的必须字段region是给GROUP BY多维分组用的特别地孙悦的工资设为NULL这是故意埋的雷——练聚合题时你会撞上AVG忽略NULL的现象正好检验你对三值逻辑的理解。插入完数据后先跑一句SELECT * FROM emp;确认环境可用。这一步的价值在于后面做任何题你都能立刻看到“答案”而不是只看着答案文本猜测结果。实践下来SQL 能力提升最快的方式不是背诵而是建库、写题、跑题、故意写错、看报错信息。3. 答案怎么用才对从“对答案”到“验证执行结果”很多人的练习流程是“做题—翻答案—看懂了—下一题”。这个流程最大的问题是你以为的“懂了”其实是“看懂了别人的思路”和自己能写出来是两回事。更糟糕的是doc 里的答案可能是错的、可能是针对特定数据库方言写的、可能忽略了 NULL 边界。所以拿到答案文档后第一件事是承认它是一个“参考实现”不是“标准裁决”。3.1 答案核对前先建立四个验证维度我自己核对答案时不看“是不是一样”而是看“结果对不对、边界全不全、方言合不合、性能好不好”。下面这个表可以作为核对工具核对维度要问的问题常见雷区逻辑等价答案的写法和你自己的写法是否都能算出同一组行用IN和EXISTS结果相同但执行计划差异很大聚合完整性有GROUP BY的题SELECT里是否只出现了分组列和聚合函数多加一个普通字段结果可能错乱NULL 边界如果某列为NULL这个查询会漏掉这行吗WHERE salary 8000会丢掉 NULL 工资的行方言适配题目的LIMIT在 SQL Server 里能不能直接跑SQL Server 用TOPMySQL 用LIMITOracle 用FETCH FIRST每做完一道题至少对着这四个维度过一遍。比如查询每个部门的平均工资标准的答案是SELECT dept_id, AVG(salary) FROM emp GROUP BY dept_id;此时如果你看到SELECT dept_id, emp_name, AVG(salary)...这样的答案不管它是不是能跑出结果它都是不合格的写法——因为emp_name既不在分组列里也不是聚合函数属于“逻辑上随机取值”的隐患写法。3.2 哪些题的答案必须自己改写一遍才能信我在实际用这类 doc 时有三类答案几乎总要动刀。第一类是“方言专属语法”。比如很多 doc 会用SELECT TOP 3 * FROM emp ORDER BY salary DESC;这在 SQL Server 里是地道的但如果你平常用 MySQL必须改成SELECT * FROM emp ORDER BY salary DESC LIMIT 3;。不是谁对谁错是不同数据库对“取前 N 行”的语法实现完全不同。第二类是“省略边界条件的答案”。比如查询“工资大于平均工资的员工”有的 doc 直接给SELECT emp_name, salary FROM emp WHERE salary AVG(salary);这条 SQL 在任何数据库里都跑不了——因为聚合函数不能直接出现在WHERE里。正确的写法是“子查询”SELECT emp_name, salary FROM emp WHERE salary (SELECT AVG(salary) FROM emp);如果你只看答案的逻辑很难发现第一种是错的但只要你把它扔进数据库跑一下立刻会看到一个报错。这就是建库的价值——答案不能用眼睛验证要用执行结果验证。第三类是“结果正确但性能可疑”的答案。比如关联查询里有人习惯先把两张大表JOIN完再WHERE有人习惯先WHERE过滤小结果集再JOIN。对于练习阶段前者问题不大但对于慢 SQL 优化场景这类先后顺序影响执行计划留给第 5 章讲。4. 避坑对照答案刷题时最常翻车的五个细节带新人时我发现一个普适规律看答案时觉得都会上机写时全不对。原因集中在几个固定的坑上。把这些坑提前排掉能省掉一半的翻车时间。4.1 现象COUNT(*)和COUNT(字段)统计结果不一样明明是同一条查询用COUNT(*)数出来 5 行用COUNT(salary)数出来只有 4 行。原因是COUNT(字段)会忽略NULL而COUNT(*)会数所有行。在工资表里孙悦的工资是NULL所以COUNT(salary)只数出 4。解决方式先弄清楚业务上到底想数“有多少人”还是“有多少人有工资”——这决定了用哪个函数。练习文档里这个坑极其常见尤其是统计类答案里很多作者不自觉写了COUNT(字段)却没在说明里提示 NULL 行为。4.2 现象WHERE和HAVING混用导致结果差一行写“查询平均工资大于 10000 的部门”时容易写成WHERE AVG(salary) 10000报错后改成HAVING AVG(salary) 10000放在GROUP BY后面但又混进了一个WHERE过滤条件把本应该参与聚合的行提前过滤掉了。原因WHERE是在分组前过滤行HAVING是在分组后过滤组。解决先写WHERE过滤掉不需要的明细行再GROUP BY分组最后HAVING过滤分组结果。举个例子“查询平均工资大于 10000 的部门且只看华东地区的部门”顺序必须是SELECT dept_id, AVG(salary) AS avg_sal FROM emp WHERE region 华东 GROUP BY dept_id HAVING AVG(salary) 10000;如果提前在WHERE里过滤工资聚合的基数就错了。4.3 现象LEFT JOIN 后行数变多答案对不上比如查“每个员工和他的部门名”用INNER JOIN后是 4 行用LEFT JOIN却查出了 7 行。原因关联字段有重复值——emp表里如果有两个员工属于同一个dept_idJOIN会把两行都匹配出来所以行数膨胀。这在练习文档的多表题里是重灾区尤其是当题目没有说明“部门表与员工表是否一对多”时。解决先对附表的关联字段做去重确认再看行数。执行下面的检查语句SELECT dept_id, COUNT(*) FROM dept GROUP BY dept_id HAVING COUNT(*) 1;如果查出重复说明关联字段不是唯一的JOIN膨胀是预期行为。这时候要么用DISTINCT去重要么先聚合再关联。4.4 现象旧版答案在大版本数据库里直接报错一份 doc 里的答案可能是针对 SQL Server 2008 R2 或 MySQL 5.7 写的而你现在用的是 SQL Server 2019 或 MySQL 8.0。典型报错包括WITH cte AS ...在老版本不支持、窗口函数语法在旧版本不存在、STRING_AGG在高版本才有。解决先看答案里的函数是不是当前版本支持的不确定就统一用“子查询 临时表”这类通用写法兼容。SQL Server 2019 和 2022 对STRING_AGG支持很好但你在 2012 上跑就会碰到问题。练习时我的习惯是题目的目标数据库是什么版本就把答案跑在什么版本上没有注明版本时优先用 ANSI 标准 SQL 而非方言特性。4.5 现象AI 生成的答案看着工整一跑就是语法错误现在很多 doc 里的答案是从 AI 对话里直接粘出来的。AI 生成 SQL 的特点是“表面流畅、细节粗糙”常常混用LIMIT和TOP、把DATEADD写在不支持的数据库里、漏掉GROUP BY的非聚合列。而且 AI 很喜欢把一条简单查询写复杂——用三层子查询来完成一个WHERE就能解决的事。这类答案你用眼睛看是看不出来的只有放进数据库跑一遍才见真章。解决保持“先验证、后相信”的习惯任何答案在复制进自己的笔记前必须至少执行一次并确认结果行数与题目预期一致。这一点在练习阶段的重要性甚至高于题目本身。5. 把静态题练成真本事从背答案到能应对面试变体文档里的题是死的但面试官手里的题是活的。同一个知识点题目换个过滤条件、换个表结构、换一个关联方向很多人就懵了。原因在于练习时只记住了答案没记住答案背后的“决策链”。这一章讲怎么把 doc 里的 50 道题练成能应对变体的内功。5.1 错题驱动的三轮刷题法我的做法是同一个 doc 刷三轮每一轮都关掉答案独立写。第一轮用最短路径写对即可不会就翻答案看完合上再写一遍第二轮开始给每道题加一个变体条件比如把“工资大于平均工资”改成“工资大于自己部门的平均工资”这需要关联子查询甚至窗口函数第三轮只看题目列表不看答案限时做完然后用第 3 章的四个维度核对。轮次核心任务变体方式核对手法第一轮把不会的题变成会的题原题直接写跑通即为通过第二轮把原题改成变体扩展边界改排序字段、改分组维度、改过滤条件对照原答案看逻辑差异第三轮限时模拟面试状态综合题一道题含 JOIN GROUP BY 子查询四个维度全面核对第二轮最值得投入时间。比如原题是“查询每个部门的最高工资”我一般会把它改成“查询每个部门最高工资对应的员工姓名”。这就要用到窗口函数SELECT dept_id, emp_name, salary FROM ( SELECT dept_id, emp_name, salary, RANK() OVER (PARTITION BY dept_id ORDER BY salary DESC) AS rk FROM emp ) t WHERE rk 1;这里的关键是RANK()按部门分区、按工资排序rk 1取出每个部门最高工资的人。如果两个人工资并列RANK()会同时给 1 号排名就不会漏人。这道变体题就是面试里“每个 X 的前 N 名”的标准考法而原版 doc 里通常只有“最高工资”这种简单聚合。刷到第二轮你能写出上面这条面试遇到窗口函数题基本就稳了。5.2 去重和排序练习答案里最容易被忽略的两个性能点“sql语句去重”是工作中最常见的需求也是 doc 练习里最容易被浅化的点。很多练习答案用DISTINCT去重但它只适合“整行去重”当你需要“按某个字段去重同时保留其他字段的最新值”时DISTINCT根本无能为力。工作中真实场景是订单表里有用户的多个订单要保留每个用户最新的一条订单。这时候答案是ROW_NUMBER()SELECT user_id, order_id, order_time FROM ( SELECT user_id, order_id, order_time, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY order_time DESC) AS rn FROM orders ) t WHERE rn 1;如果 doc 里没有这题建议自己加上。面试官很喜欢把它藏在“统计每个用户的最近一次登录”这类业务题里。另一个容易被忽略的是排序字段的索引影响——练习阶段小数据量看不出来但一到生产环境一个在千万级表上的ORDER BY没有索引支撑就是教科书级别的慢 SQL 优化靶子。答案文档里不会告诉你“这条查询在数据量大时怎么改”但这个意识得自己建立起来先看执行计划再谈写法。5.3 把 doc 里的题改造成自己的面试速查手册刷完三轮之后最高价值的产出不是“我做完了一本 doc”而是一份“自己的速查手册”。我会把每道题按“知识点 我的写法 踩过的坑 变体追问”四个字段重新整理。比如“查询每个部门平均工资”这条手册里记的是知识点GROUP BYHAVING我的写法SELECT dept_id, AVG(salary) FROM emp GROUP BY dept_id;踩过的坑WHERE不能直接放聚合函数COUNT(salary)会忽略 NULL变体追问平均工资大于 10000 的部门——加HAVING AVG(salary) 10000这样整理完doc 就不再是一份别人的练习材料而是你自己的面试武器库。面试前翻这个手册比从头到尾刷 doc 高效得多因为你直接看到了自己的薄弱点。同时这本手册里的每一个实例都是你亲自跑过、验证过的真到要给别人讲的时候也能说清楚为什么这么写——这在技术面试里是极大的加分项。6. 进阶玩法把一份静态 doc 变成一套持续进化的 SQL 练习环境到这里你已经不会再把“sql语句练习题及答案.doc”当成一次性学习资料了。我的习惯是任何一份练习文档最终都要变成一个小小的本地“教练系统”用一套固定的练习库 一份错题记录表 每周一次的重刷。具体做法是三步走。第一步把 doc 里的题按难度分成三层语法基础层SELECT/WHERE/ORDER BY、单表逻辑层GROUP BY/HAVING/CASE WHEN/ 子查询、多表关联层JOIN/ 窗口函数对应不同阶段去刷。第二步每周从错题记录表里随机抽 5 道变体题限时 15 分钟写完跑通之后再复盘。第三步每两周新增一道自己工作中遇到的真实取数需求改造成练习题写进 doc 的附录——这样题库就是活的而不是停留在纸面的 50 道题。我个人吃过亏的地方是刚开始刷题时只求“看懂”从来不上机跑结果面试写LEFT JOIN和INNER JOIN时犹豫了很久因为根本不知道两张表关联后数据会不会膨胀。后来改成“先建库、再做题、最后对答案”的流程完全不一样了。那份 doc 我至今还留着但它的意义已经不是答案本身而是当初逼着我给自己建练习库的起点。如果你想在这个方向投入建一个本地库跑通这十类题比买十份新的 doc 都有用。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?