新闻详情

新闻详情

首页 / 资讯中心 / 详情

SQL刷题全记录:从窗口函数到慢SQL优化实战指南

发布时间:2026/9/25 2:54:41来源:尧图网络
SQL刷题全记录:从窗口函数到慢SQL优化实战指南
1. 为什么我重新开始刷SQL题刷题到底在刷什么先说个背景。我自己写了七八年业务代码SQL一直属于能跑就行的水平——要什么数据就写什么查询跑得慢就加个索引实在不行就把数据捞到内存里用程序处理。直到有一次帮同事排查一个统计报表发现一条三表关联的查询跑了四十多秒我盯着执行计划看了半小时才意识到自己的SQL水平其实一直停在会写而不是会想。那段时间正好在准备一些面试面了几家公司之后更受刺激同样的业务场景人家问的是窗口函数怎么处理同环比怎么用一条SQL找出连续登录三天以上的用户数据量到千万级别之后这个查询为什么慢而我脑子里只有GROUP BY和子查询。所以从那时候开始我给自己定了一个硬性计划每天刷SQL题并且把每一道题的过程、解法、踩过的坑都记录下来这就是这份SQL刷题记录的由来。刷题刷的是什么很多人以为刷题就是背语法、记函数、攒题量我觉得这个理解偏差很大。语法和函数当然要熟但那只是入场券。SQL题真正锻炼的是三样东西第一是建模能力。拿到一个需求能不能快速把它拆成我需要哪几张表、以哪张表为驱动表、表之间是什么关系、结果集的粒度是什么样的。这个能力不通过大量做题是练不出来的看再多教程也没用。第二是对集合思维的理解。SQL和程序语言最大的不同在于它不是逐行处理数据而是面向集合操作。新手写SQL经常带着循环遍历的思维比如为了算累计值非要用子查询一行一行关联而窗口函数一行就能解决。这个思维转换只有靠大量对比解法才能扭转。第三是排查和优化能力。这一点放到后面的章节详细说。刷题阶段遇到的每一条慢查询、每一个错误结果其实都是生产环境问题的预习。我给自己定的刷题范围比较杂LeetCode的数据库题库、各类面试题合集、公司内部沉淀的业务SQL题还有自己工作中遇到的实际查询问题。刷题不是目的记录才是。我每做完一道题都会把题目、我的解法、优化后的解法、涉及的知识点、踩的坑整理到笔记里。这份记录积累下来之后回头翻看的价值比刷题本身大得多。2. 刷题环境、资源与节奏我踩过的准备阶段坑2.1 本机环境选型SQL Server版本怎么选刷题第一步要有个能跑SQL的环境。我在选择时考虑的是国内多数公司的生产环境以SQL Server和MySQL为主所以主刷环境选了SQL Server。这里第一个坑就是版本选择。热搜词里大量出现SQL Server 2022下载SQL Server 2019安装教程SQL Server 2016安装SQL Server 2008 R2安装包下载说明很多人卡在环境安装这一步。我的建议是别盲目装最新版也别抱着老版本不放。2022版本本身有很多新特性比如查询存储的增强、并行处理的优化但如果你只是为了刷题用2019甚至2016完全够。核心原因是刷题用的语法窗口函数、CTE、LAG/LEAD、STRING_AGG从2016开始就基本齐全了没必要为用不上的新特性承担更多的安装配置成本。我自己最终装了SQL Server 2019 Developer版配SSMS 18版本。Developer版免费功能和企业版一致只限制不能用于生产环境刷题学习完全够用。这里有个容易踩坑的点SSMS和SQL Server是两个独立的东西热搜词里SQL Server 2008可以和SSMS 2022共存吗就是这个问题。SSMS是客户端管理工具SQL Server是数据库引擎两者版本不需要一致。高版本SSMS可以连接低版本的数据库引擎只是部分新功能在旧引擎上不可用。我现在的组合是SQL Server 2019引擎较新版本的SSMS日常使用没有任何问题。如果安装过程中遇到SQL Server 2008 R2提示对密钥无访问权限这类报错多半是安装包管理权限的问题。以管理员身份运行安装程序或者检查安装包是否被系统拦截了。这类问题在官方文档里写得并不显眼实际遇到时浪费了我不少时间。2.2 刷题数据的准备练习题和测试数据的坑环境装好之后第二个坑是数据。很多人刷SQL题时直接用LeetCode内置的测试数据这当然可以但有个明显问题数据量太小随手一写就是正确答案根本体会不到性能差异。一道题按正确的标准做出来了但解法是不是高效完全没概念。我的做法是搭了一套自己的测试库数据量和数据特征刻意做了区分。比如有一张订单表我插入了100万行测试数据金额字段里定期混入NULL值订单时间有大量重复值客户名称里混入了全角空格和大小写不一致的情况。为什么要这么干因为实际业务数据从来不会像刷题网站那样干净。真实场景里NULL值、重复值、脏数据才是常态。而这些恰恰是面试和工作中最常被问到的东西——热搜词里的SQL去除空值SQL语句去重清洗SQL语句去重都是这一类问题。练习题资源方面我用的比较杂LeetCode数据库板块适合入门题目场景设计得好但数据量太小各类SQL面试题合集更贴近国内公司的面试风格经常直接考业务场景自己工作中的真实查询需求这个价值最高后面专门讲第三个坑是节奏。我开始时给自己定了每天刷五题的计划结果坚持了三天就崩了。后来调整成每天一题周末加两题反而坚持了半年。刷题这件事持续性比强度重要得多。3. 高频题型的拆解从窗口函数到去重与空值3.1 窗口函数刷题记录里出现频率最高的一类翻我的刷题记录出现频率最高的知识点就是窗口函数。热搜词里SQL窗口函数排得很靠前这不是偶然。窗口函数几乎是区分SQL入门和熟练的分水岭。先说什么场景必须用窗口函数。最典型的是分组TopN问题查每个部门工资最高的员工。用GROUP BY只能拿到每个部门的最高工资但拿不到这个人是谁因为分组后其他字段就丢了。传统解法是自关联或者用子查询先找出最高工资再关联回去SELECT e.* FROM employee e JOIN ( SELECT dept_id, MAX(salary) AS max_salary FROM employee GROUP BY dept_id ) t ON e.dept_id t.dept_id AND e.salary t.max_salary这个解法能出结果但有个隐含问题如果同一个部门有两个人的工资都是最高值结果会重复如果表很大这个自关联的代价也不低。窗口函数的做法是SELECT dept_id, emp_name, salary FROM ( SELECT dept_id, emp_name, salary, ROW_NUMBER() OVER (PARTITION BY dept_id ORDER BY salary DESC) AS rn FROM employee ) t WHERE rn 1两种解法一对比窗口函数的优势就很明显不用做关联直接在原表上开窗排序逻辑更清晰执行效率也更高。我刷题记录里总结过一句话凡是每组内按某个顺序取第几条的题优先想窗口函数。窗口函数里常用的三件套是ROW_NUMBER()、RANK()、DENSE_RANK()三者的区别是并列名次的处理方式不同这个面试经常考。还有LAG()和LEAD()用来取当前行的前一行或后一行做同环比、连续登录判断非常好用。SUM() OVER (ORDER BY ...)这种累加写法处理累计值场景一绝。3.2 去重与空值看起来简单做起来全是坑SQL语句去重这个热搜词几乎贯穿了所有SQL学习者的成长路径。它看起来简单DISTINCT四个字母就完事了但我刷题记录里关于去重的笔记至少有十条因为这个操作背后藏着好几个坑。坑一是DISTINCT的粒度。很多人以为DISTINCT是对字段去重其实它是去重一整行。比如要查所有不重复的客户IDSELECT DISTINCT customer_id没问题但如果要查客户ID和订单时间并且每个客户只保留一条记录DISTINCT就做不到了。这时候需要GROUP BY或者窗口函数SELECT * FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY order_date DESC) AS rn FROM orders ) t WHERE rn 1坑二是去重时选哪条记录。上面这个SQL是按订单时间倒序后取第一条也就是每个客户最近的订单。实际业务里保留哪条往往有明确的业务规则刷题时最容易漏掉这个考虑直接用GROUP BY取了个随机值。坑三是和空值纠缠在一起。COUNT(DISTINCT column)不会把NULL计入在内COUNT(column)同样忽略NULL而COUNT(*)会计入所有行。很多统计报表的差异根源就在于这三个计数的写法不同。我刷题记录里专门有三种计数方式的区别这一条因为实际工作中遇到过两次因为这个导致报表对不上账的问题。处理空值NULL同样是高频考点。常用的函数是ISNULL、COALESCE。ISNULL(SQL Server)只能接受两个参数COALESCE可以接受多个参数取第一个非NULL值。判断空值要写IS NULL而不是 NULL——这个看起来基础到没人会错的问题我在实际生产代码里见过不止一次。3.3 字符串与类型处理被低估的得分点热搜词里的DB2 SQL判断数字字符串函数和SQL默认值GUID让我想起另一个刷题时容易忽略的类别——字符串和类型的处理。字符串函数在不同数据库里差异很大。SQL Server里有ISNUMERIC()判断字符串能否转成数字但它是全局判断比如ISNUMERIC(1e3)返回1而这个字符串转成整数会失败。DB2里有TRANSLATE函数可以去掉非数字字符后再做判断。跨数据库刷题时这类差异值得单独记一笔因为实际工作中数据库迁移的场景越来越多。GUID作为主键默认值在SQL Server里是NEWID()或NEWSEQUENTIALID()。后者生成顺序GUID减少页拆分。刷题时很少考这个但实际建表时它直接影响写入性能。我自己的记录里加了一条能用自增ID做主键就别用GUID非要GUID就考虑NEWSEQUENTIALID。这是从生产环境的教训得来的经验。4. 慢SQL与优化题把刷题延伸到生产环境4.1 一道优化题的标准排查链路热搜词里慢SQL优化并行SQL优化这两个词说明这已经是普遍的痛点。我的刷题记录里专门有一个分类叫优化题——这类题目给一个慢查询要求你找出原因并优化。我做这类题的标准链路是这样的第一步看执行计划。在SQL Server Management Studio里按快捷键CtrlM打开显示实际执行计划然后执行查询。如果查询很慢执行计划也能显示出来只是要等。执行计划里重点关注几个东西表扫描Table Scan还是索引查找Index Seek、估算行数和实际行数的巨大差异、警告图标比如缺失索引提示。第二步找高开销操作。执行计划里每个算子旁边有个百分比表示它在整个查询里占用的开销比例。通常最扎眼的是键查找RID Lookup / Key Lookup——说明索引覆盖不够查询返回列里有不在索引中的字段每查一行都要回表。第三步优化策略。要么加索引要么改写法要么改表结构。加索引不是所有查询字段都加一遍而是根据WHERE条件、JOIN关联键、ORDER BY字段来定。覆盖索引在索引里包含查询需要的所有列可以消除回表但也别滥用——每个索引都会拖慢写入。执行计划很多人看不太懂我刚开始也卡在这里。这里分享一个笨办法把同一条查询改成不同写法然后对比执行计划的变化。比如把子查询改成JOIN、把OR改成UNION、把函数从WHERE禁止用在字段上每一次改动后看执行计划的变化比硬啃文档有效十倍。4.2 最容易被问到的优化知识点刷题记录里关于优化的笔记最多高频规律也很集中避免在WHERE子句的字段上用函数。WHERE DATE(order_time) 2024-01-01会导致索引失效改成order_time 2024-01-01 AND order_time 2024-01-02就能走索引。这个知识点几乎每次面试都会被问到。尽量避免隐式转换。字段类型是VARCHAR传入参数是数字SQL Server会在比较时偷偷转换类型索引照样失效。OR条件要小心。OR可能让优化器放弃索引合并性能差得离谱的场景拆成UNION ALL往往立竿见影。只SELECT需要的列。在刷题网站里无所谓在生产环境里SELECT *会把所有列都捞回来浪费IO和网络带宽。并行SQL优化是另一个被广泛搜索的点。SQL Server有时候会为一条查询分配多个并行线程结果反而因为线程调度开销变慢。遇到这种情况OPTION (MAXDOP 1)能强制单线程执行。虽然不建议无脑加这个Hint但在特定并发场景下尤其OLTP系统里限制并行度经常能让慢查询起死回生。我之前遇到过一条查询数据量才几十万行却跑出了两分多钟。执行计划一看扫描次数惊人优化器选择了并行但资源争抢严重。加了一个MAXDOP 1提示后查询降到几秒。这个案例最后也写进了刷题记录标注为并行不等于更快。5. SQL Server使用中的常见报错与配置坑5.1 SSL加密连接报错新版本的一个经典坑热搜词里有一条很长的条目驱动程序无法通过使用安全套接字层(SSL)加密与SQL Server建立安全连接。错误。这个报错我研究过一轮核心原因比较典型SQL Server从2016开始默认启用强制加密而客户端驱动或连接字符串没有适配新加密协议。我自己重装系统后配环境时遇到过这个报错当时的处理方案有两个方向。一个是客户端方向在连接字符串里加EncryptFalse不同驱动写法不同。一个是服务端方向在SQL Server配置管理器里把Force Encryption设为No。但注意这只适用于本地开发测试环境生产环境还是应该保持加密。这个问题的另一个隐蔽点是证书。SQL Server在加密时需要一张证书如果本机没有配置合适的证书连接就可能失败。解决办法是给SQL Server配置一张自签名证书或者使用机器自带的证书。网上大量的SQL Server 2022安装教程里都会提这一嘴但实际遇到报错时大家还是容易懵因为报错信息里的SSL字样容易让人误以为是网络问题。5.2 内存占用与其他经典配置问题热搜词里SQL Server Windows NT占用内存这个问题我在刷题过程中也专门研究过。SQL Server的行为和普通应用不一样它会尽量吃掉可用内存作为缓冲池缓存数据。这本身是特性而不是缺陷但很多人第一次装完发现内存被占掉大半就慌了。如果确实需要限制可以在SSMS里右键服务器属性在内存页设置最大服务器内存。我开发机上设置的是2048MB刷题完全够用。生产环境的内存设置需要结合数据量、并发、实例上跑多少个库来综合评估不能拍脑袋。还有一个常见的兼容问题SQL Server 2012的数据库备份2008能用吗。结论是不能直接降级还原。低版本引擎无法附加高版本数据库文件备份文件也一样。解决办法是使用生成脚本的方式把结构和数据导到低版本或者用第三方工具做迁移。刷题时如果碰到跨版本还原报错基本就是这个原因。5.3 在SQL Server中执行多句SQL热搜词里c#怎么执行多句SQL语句也是个操作层面的常见问题。在SQL Server Management Studio中一条批处理里可以写多条语句用分号隔开。在应用程序代码里C#的SqlCommand可以一次执行包含多条语句的CommandText但要注意如果第一条语句执行失败同一批里的后续语句不一定全部回滚除非显式包在事务里。这个细节在生产代码里很重要很多数据不一致的问题就出在这里。刷题时我习惯把多步操作写成一个批处理用BEGIN TRANSACTION包起来验证完数据没问题再COMMIT。练习阶段养成这个习惯到了生产环境就能少踩大坑。6. 刷题之外从题解到业务查询的落地习惯6.1 把面试题翻译成业务场景刷题到一定阶段我发现自己陷入了一个舒适区LeetCode上的题都能做出来了但回到工作中遇到业务部门提的报表需求还是要想很久。后来我想明白了一个问题——刷题时面对的是设计好的表和明确的问法业务场景则完全不是这么回事。于是我开始刻意做一种练习把刷过的每一道题改写成现实中会遇到的需求。比如查每个部门工资排名前3的员工我改成查每个区域销售额排名前3的店铺且销售额小于0的要过滤掉查连续登录3天的用户改成查连续3个月有采购记录的供应商。这个习惯带来的改变非常明显。因为改写的过程强迫我思考业务逻辑中隐藏的条件——哪些数据是无效数据、怎么定义连续、时间粒度是按天还是按月、并列怎么处理。这些都是面试题里不会直接告诉你的隐含条件而实际业务恰恰是被这些隐含条件左右的。6.2 用一份适合自己的速查笔记替代收藏夹最后的经验是笔记管理。我尝试过收藏各种SQL语句大全SQL优化技巧之类的文章最终发现收藏等于忘记。真正有效的是自己整理一份速查笔记格式很简单知识点名称、场景、示例SQL、踩过的坑。每做完一道有价值的题就往笔记里加一条每次解决一个实际业务问题也往笔记里加一条。速查笔记和收藏夹最大的区别是收藏夹里的内容是别人写的结构、侧重、表达方式都是别人的思路速查笔记里的每一条都凝结了自己真实解决问题的过程遇到类似问题时能更快回忆起来、更快定位。比如我在笔记里记录过窗口函数为例的问题旁边就备注了查最近一次订单时PARTITION BY后面不要漏掉客户维度的过滤条件——这种细节在教科书里根本找不到只能来自实践。刷题刷到最后收获的从来不是题量本身而是面对一个模糊需求时能迅速从笔记里、从做过的题中找到对应的解决方案和排查思路。这是我认为SQL刷题记录最核心的价值所在。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Fission 仓库 CHANGELOG 深度解读:Kubernetes 无服务器框架的版本演进与源码印证 2026/9/25 3:30:13

Fission 仓库 CHANGELOG 深度解读:Kubernetes 无服务器框架的版本演进与源码印证

云原生后端 【免费下载链接】fission Fast and Simple Serverless Functions for Kubernetes 项目地址: https://gitcode.com/gh_mirrors/fi/fission 点击查看 免费下载 本文以 Fission 仓库根目录的 CHANGELOG.md 为绝对主线,梳理该项目自 2017 年 0.3…

阅读更多 →
Claude代码模板不是CLI工具:MCP协议级模板规范解析 2026/9/25 3:30:13

Claude代码模板不是CLI工具:MCP协议级模板规范解析

1. 这不是又一个 CLI 工具:Claude-Code-Templates 的真实定位与误读陷阱很多人第一次看到claude-code-templates这个名字,下意识就把它当成“Claude 官方推出的命令行代码生成器”——就像create-react-app或vite那样,敲一行命令就能拉起一个…

阅读更多 →
eslint-plugin-react 的 react/jsx-no-leaked-render 规则:阻止 `` 条件渲染泄漏 0、NaN 等危险值 2026/9/25 3:30:13

eslint-plugin-react 的 react/jsx-no-leaked-render 规则:阻止 `` 条件渲染泄漏 0、NaN 等危险值

开发工具代码质量静态分析 【免费下载链接】eslint-plugin-react React-specific linting rules for ESLint 项目地址: https://gitcode.com/gh_mirrors/es/eslint-plugin-react 点击查看 免费下载 react/jsx-no-leaked-render 是 eslint-plugin-react 中专门用于拦…

阅读更多 →
在线听歌网站推荐:聚合搜索与自建曲库方案全解析 2026/9/25 3:30:13

在线听歌网站推荐:聚合搜索与自建曲库方案全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
告别Vuex,拥抱Pinia:Vue3状态管理实战指南 2026/9/25 3:30:12

告别Vuex,拥抱Pinia:Vue3状态管理实战指南

做后台管理系统这几年,我先后经历了 Vue2 Vuex 到 Vue3 Pinia 的切换,说实话刚开始是有点抗拒的,毕竟 Vuex 用了那么久,突然来个新东西总觉得又要重新学一遍。但真正把 Pinia 用进项目之后,最大的感受就是&#xff1…

阅读更多 →
Humanizer 流式日期 API 实战:On.March 类完整参考与源码实现解析 2026/9/25 3:30:06

Humanizer 流式日期 API 实战:On.March 类完整参考与源码实现解析

开发工具 【免费下载链接】Humanizer Humanizer meets all your .NET needs for manipulating and displaying strings, enums, dates, times, timespans, numbers and quantities 项目地址: https://gitcode.com/gh_mirrors/hu/Humanizer 点击查看 免费下载 本篇指…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉