很多人觉得SQL难学,其实不是SQL本身难,而是大多数人一上来就抱着语法文档啃,结果SELECT、WHERE、JOIN都会写,真给你一张表、一个查询需求,脑子就卡壳了。我从带新人的经验来看,快速提升SQL水平最有效的路径就是刷题,而且不是刷那种零散的题,是一套覆盖核心知识点的练习集。"sql语句练习50题"这套题我用了很多年带新人,也反复推荐给准备面试的朋友,它覆盖了从基础查询、聚合分组、多表连接到子查询、窗口函数的完整链路,练完一遍,日常开发和面试中的绝大多数SQL场景都能应付。这篇内容我就把这套练习题的拆解思路、核心知识点、代表性题目的解题过程、高频报错的排查方法,以及从练习到实战的衔接经验完整分享一下,适合SQL刚入门、准备数据库面试、或者工作两三年想系统补一下SQL基础的开发者。
1. 为什么我建议用"50题练习"作为SQL学习的主线
1.1 学SQL最常见的三个坑
我见过太多人学SQL的方式是:买一本《SQL必知必会》,从头翻到尾,每个语法都看懂了,然后关上书,遇到真实的查询需求还是不知道怎么写。这是第一个坑——把SQL当知识学,而不是当技能练。SQL本质上是一门操作语言,它的学习路径应该是"需求→语法→实现",而不是"语法→语法→语法"。
第二个坑是只会在单表上做简单查询。很多初学者练到SELECT、WHERE、ORDER BY就觉得差不多了,一碰到JOIN就发怵,碰到GROUP BY和HAVING的组合就晕头转向。但真实业务里,数据几乎不会乖乖躺在一张表里等你去查,你需要面对的是订单表、用户表、商品表、日志表这些分散在不同表里的数据,把多张表关联起来的能力才是SQL实战的骨架。
第三个坑更隐蔽——刷题只看答案不自己写。网上确实有"SQL练习50题带答案"的资料,很多人一上来就打开答案看一遍,觉得自己会了,实际上手还是写不出来。SQL能力必须经过"自己卡住→翻资料→写出来→再优化"这个过程才能真正内化,只看答案等于没练。
1.2 这套练习集的设计逻辑与知识覆盖
之所以推荐"50题"这种规模的练习,是因为这个体量刚好能覆盖SQL核心知识体系的全部关键节点,又不至于多到让人望而生畏。我拆解了一下这套题的知识覆盖,大致按照这个难度梯度铺开:
- 基础查询类(SELECT、WHERE、DISTINCT、ORDER BY、LIMIT/TOP)
- 条件筛选类(IN、BETWEEN AND、LIKE、AND/OR优先级、NULL处理)
- 聚合统计类(COUNT、SUM、AVG、MAX/MIN、GROUP BY、HAVING)
- 多表连接类(INNER JOIN、LEFT JOIN、RIGHT JOIN、自连接、笛卡尔积避免)
- 子查询类(标量子查询、IN子查询、EXISTS子查询、嵌套子查询)
- 窗口函数类(ROW_NUMBER、RANK、DENSE_RANK、SUM OVER、LAG/LEAD)
- 综合应用类(行转列、列转行、分组排序取TopN、同比环比、连续值判断)
这个覆盖范围和各大厂数据库面试题的知识点高度重合。换句话说,把50题认真啃下来,你等于把所有SQL高频考点都过了一遍,后面去面试或者做业务需求,心态会完全不一样。
1.3 练习环境怎么选
提一句练习环境。50题本身并没有绑定某个具体的数据库产品,但很多初学者会在环境选择上卡住。我的建议是:如果你有明确的工作方向,就按公司用的数据库去搭环境,比如公司用SQL Server就装SQL Server 2019/2022,用MySQL就装MySQL 8.0;如果还没想好方向,优先选MySQL 8.0,因为它的语法兼容性好,网上资料也最多。
SQL Server 2008 R2这种老版本就真的不建议再装了,语法支持、工具链都太旧,装起来还容易遇到系统兼容问题。搭建环境的时候,重点确认三件事:服务能正常启动、能用命令行或客户端工具连上数据库、能执行基础的建表和插入语句。这三件事通了,就可以开始刷题了。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心知识点拆解:50题背后藏着的SQL能力模型
2.1 基础查询与过滤:不只是SELECT和WHERE
很多人觉得基础查询太简单,不值得花时间。但实际上,50题里最前面那批"简单题",恰恰是很多人后面写复杂查询出错的老根子。比如DISTINCT的去重逻辑,它是对整个结果集的行去重,而不是对某一列去重,这个语义不搞清楚,后面写"查询每个部门有多少个不同岗位"这类题就会出错。
BETWEEN AND的边界是另一个高频坑。在SQL Server和MySQL里,BETWEEN AND是包含边界的,也就是说WHERE age BETWEEN 18 AND 25会把18岁和25岁都算进来。很多人想当然地以为是开区间,结果统计数字对不上。再比如AND和OR的优先级——AND的优先级高于OR,所以WHERE a = 1 OR a = 2 AND b = 3实际执行的是a = 1 OR (a = 2 AND b = 3),如果不记得加括号,逻辑就完全跑偏了。这类细节在平时开发时可能影响不大,但在练习阶段不搞清楚,面试问到底层执行逻辑时就会露馅。
NULL值的处理也是基础题里绕不开的坎。WHERE name = NULL是永远查不出数据的,必须用IS NULL或者IS NOT NULL。更麻烦的是NULL在聚合函数里的表现——COUNT(列名)会忽略NULL,但COUNT(*)不会;SUM遇到NULL会直接跳过而不是当作0。50题里会有好几道题专门考察这些点,初学者在这上面栽两次跟头,印象会非常深刻。
2.2 聚合与分组:统计类题目的核心思维
刷到聚合统计这些题,才算真正摸到SQL分析的门槛。我常说一句话:单表查询考的是语法熟练度,聚合查询考的才是分析思维。50题在这里会反复训练你一个核心心智模型——先分组、再聚合、后筛选。
很多人写分组统计时,第一步就卡在"到底哪些列要放进GROUP BY"。口诀很简单:SELECT后面出现的非聚合列,必须全部出现在GROUP BY子句中。比如"查询每个部门的平均工资"就是SELECT dept, AVG(salary) FROM emp GROUP BY dept。但"查询每个部门每个岗位的平均工资"就需要GROUP BY dept, job。如果漏掉一个分组列,SQL虽然不会报错,但统计出来的结果绝对是错的。
另一个容易混淆的是WHERE和HAVING的分工。WHERE是在分组前对原始行进行过滤,HAVING是在分组后对聚合结果进行过滤。比如"查询平均工资大于5000的部门",这个条件必须用HAVING,因为平均工资是聚合之后才有的值;但"查询工资大于3000的员工统计"就应该放在WHERE里先过滤,这样既逻辑正确又能减少分组时的数据量。
聚合题还有一个经常被低估的考点是CASE WHEN和聚合函数的组合。比如"统计每个部门工资大于5000和小于等于5000的人数",这类题用SUM(CASE WHEN ... THEN 1 ELSE 0 END)就能优雅地实现一行转多列的效果。50题里的很多综合题,本质上都是CASE WHEN + 聚合函数 + GROUP BY这三件套的组合拳。
2.3 多表连接:JOIN选型比写法更重要
多表连接是50题中占比最大、也最考验逻辑的一部分。我见过不少初学者,INNER JOIN和LEFT JOIN的区别背得滚瓜烂熟,一做题就错,根本原因是没有建立"驱动表"和"匹配方向"的直觉。
用一个生活化的类比:INNER JOIN就像去参加一个必须双方都到场的会议,两边都有记录才能出现在结果里;LEFT JOIN就像以左边那张表为"主角",不管右边有没有匹配上,左边每条记录都必须出现在结果里,右边没有匹配的字段就补NULL。所以在做"查询所有员工及其部门信息,没分配部门的员工也要显示"这类题时,脑子里第一反应就应该是LEFT JOIN,因为你已经知道员工表的记录不能丢。
还有一个很多练习者会忽视的点是自连接。所谓自连接,就是一张表自己跟自己JOIN,通常用于处理"同一张表内的上下级关系""同一张表内的两两对比"这类场景。比如"查询每个员工的姓名及其经理姓名",如果员工表和经理信息都在同一张表里,就需要把这张表分别当成"员工表"和"经理表"来连接。写法上就是FROM emp e1 LEFT JOIN emp e2 ON e1.manager_id = e2.emp_id,关键是给同一张表起两个不同的别名。这个概念在50题里至少会出现两三道,是很多人卡住的重点。
连接条件写错的问题更要重视。如果JOIN条件漏写了或者写成了笛卡尔积,结果集会呈爆炸式增长。我在练习阶段要求自己记住一条:每次写完JOIN,先看结果行数是否符合预期。比如员工表100条、部门表10条,INNER JOIN正常情况下最多100条结果;如果查出来1000条,那几乎可以断定连接条件出了问题。养成这个检查习惯,在实际工作中能帮你省下大量排查时间。
2.4 子查询与窗口函数:进阶题目的破题方法
50题练到后半程,子查询和窗口函数就成了主角。子查询的核心价值在于"分步思考"——先用一个查询拿到中间结果,再基于这个结果做外层查询。初学者最需要练的是区分IN和EXISTS的使用场景:IN适合子查询结果集很小的情况,EXISTS更关注"是否存在"这个布尔判断,在大数据量下通常性能更好。
窗口函数是近年来SQL面试的绝对热门,也是"SQL练习50题"中最具含金量的部分。窗口函数和GROUP BY最本质的区别是:GROUP BY会把多行合并成一行,窗口函数不会合并行,它是在不改变结果集行数的基础上,为每一行计算一个"窗口范围"内的聚合值。比如ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC),就能在保留所有员工记录的同时,给每个部门内部按工资从高到低编号。这个能力在"查询每个部门工资最高的员工""查询每个班级前三名"这类题目里几乎是唯一解。
窗口函数的写法有固定套路:函数名 + OVER + 括号内的PARTITION BY和ORDER BY。PARTITION BY负责划分窗口范围,ORDER BY负责窗口内的排序。还有几个容易混淆的排名函数:ROW_NUMBER()无论并列与否都返回连续编号,RANK()遇到并列会跳号,DENSE_RANK()遇到并列不跳号。50题里往往会设计一道"并列名次"的陷阱题,就是专门考察这三者的区别。
我在带人的时候发现,窗口函数不是一个可以"背出来"的知识点,必须在题目里反复使用才能形成条件反射。前几次写的时候可以翻笔记,写到第五六道涉及窗口函数的题目时,基本就能脱手了。
3. 实战解读:几道代表性题目的完整解题过程
3.1 建表与造数:练习的第一步也是最重要的一步
刷练习题之前,先把环境准备好。我强烈建议你把50题配套的建表脚本和造数语句自己敲一遍,不要直接粘贴执行。原因有两个:一是敲一遍能帮你记住表结构,后面写查询时才知道哪张表有哪些字段;二是建表语句本身也包含了很多SQL细节,比如字段类型的选择、主键约束、默认值约束等,这对初学者来说也是额外的学习素材。
以经典的员工部门练习为例,你需要准备两张核心表:
sql复制-- 部门表
CREATE TABLE dept (
deptno INT PRIMARY KEY,
dname VARCHAR(20),
loc VARCHAR(20)
);
-- 员工表
CREATE TABLE emp (
empno INT PRIMARY KEY,
ename VARCHAR(20),
job VARCHAR(20),
mgr INT,
hiredate DATE,
sal DECIMAL(10, 2),
comm DECIMAL(10, 2),
deptno INT
);
这套表结构来自经典的SCOTT练习库,字段虽然不多,但覆盖了几乎所有常用数据类型:整数、字符串、日期、小数。插数据的时候,记得故意插几条NULL值进去,比如有的员工没有提成、有的员工没有上级经理,后面练习NULL处理时就有素材了。
我用SQL Server 2019做演示,如果你装的是MySQL,语法上基本一致,个别函数名需要调整。对了,SQL Server Management Studio(SSMS)本身自带了一个"新建查询"窗口,写完SQL直接按F5就能执行,查看结果集非常方便。MySQL用户可以用DBeaver或者Navicat,体验差别不大。
3.2 经典题目一:分组统计类
用一道"查询每个部门的部门编号、部门名称、部门人数、平均工资、最高工资"来演示。这是一道非常典型的分组统计基础题,也是后面很多综合题的提法变体。
先捋一下思路:部门人数、平均工资、最高工资都是按部门维度的聚合值,所以GROUP BY的字段应该是部门维度。由于部门名称存在dept表里,员工表里只有deptno,要拿到部门名称就需要JOIN dept表。完整写法如下:
sql复制SELECT
d.deptno,
d.dname,
COUNT(e.empno) AS emp_cnt,
AVG(e.sal) AS avg_sal,
MAX(e.sal) AS max_sal
FROM dept d
LEFT JOIN emp e ON d.deptno = e.deptno
GROUP BY d.deptno, d.dname
ORDER BY d.deptno;
注意这里我用了LEFT JOIN而不是INNER JOIN,是刻意为之。如果某个部门还没有员工,INNER JOIN会把这个部门过滤掉,显示出来的结果就缺了部门;而LEFT JOIN会保留没有员工的部门,聚合值显示为NULL或0。这个细节在真实业务里很关键——你统计的是"所有部门"的情况,而不是"有人的部门"的情况。
另外,COUNT(e.empno)而不是COUNT(*),我在这里做了一个小处理。如果某个部门没有员工,LEFT JOIN后该部门在结果集里会有一行记录,但员工字段全是NULL。此时COUNT(*)会把这个部门算成1,而COUNT(e.empno)会正确算成0。虽然这道题里可能看不出来差别,但在实际业务中这是绕不开的坑。
3.3 经典题目二:子查询与JOIN的组合应用
再看一道综合性强一点的:查询每个部门中工资最高的员工的姓名、工资和所在部门名称。
很多人的第一反应是用子查询先算出每个部门的最高工资,再JOIN员工表。思路没问题,但写法上有讲究。如果直接用WHERE sal = (SELECT MAX(sal) FROM emp GROUP BY deptno)这种写法,子查询返回的是多行值,用等于号就会直接报错。
正确的做法是把"部门最高工资"这个中间结果集当作一张临时表来JOIN,这也是子查询的一个核心用法——表子查询:
sql复制SELECT
e.ename,
e.sal,
d.dname
FROM emp e
INNER JOIN (
SELECT deptno, MAX(sal) AS max_sal
FROM emp
GROUP BY deptno
) t ON e.deptno = t.deptno AND e.sal = t.max_sal
LEFT JOIN dept d ON e.deptno = d.deptno;
如果你已经学了窗口函数,这道题还有一个更简洁的解法:先用RANK() OVER (PARTITION BY deptno ORDER BY sal DESC)给每个部门内部按工资排名,然后外面套一层查询,只取排名等于1的记录:
sql复制SELECT ename, sal, dname FROM (
SELECT
e.ename,
e.sal,
d.dname,
RANK() OVER (PARTITION BY e.deptno ORDER BY e.sal DESC) AS rn
FROM emp e
LEFT JOIN dept d ON e.deptno = d.deptno
) t
WHERE rn = 1;
用RANK而不是ROW_NUMBER,是因为RANK能保留并列第一。如果公司有两个员工工资恰好相同且都是部门最高,ROW_NUMBER只会返回其中一个,而RANK会把两个都查出来。到底用哪个,取决于业务需求。练习阶段建议两种解法都写一遍,这样才能真正理解"用JOIN实现"和"用窗口函数实现"各自适合什么场景。
3.4 解题顺序与时间分配建议
50题从头刷到尾,不建议按题目编号顺序硬啃。我的习惯是把题目按难度和知识点分成三轮:
第一轮(基础热身):集中做基础查询、条件筛选、排序去重这些题,目标是语法不出错,每道题控制在3到5分钟内。这一轮不要追求"巧解",老老实实用最直白的方式写。
第二轮(核心攻坚):主攻聚合统计、多表连接、子查询,这是50题的大头。每道题做完后,强制自己再看一眼官方答案(或网上公开的参考答案),对比一下思路差异。如果参考答案用了你没用过的方式,一定要搞懂再进入下一题,不要带着知识盲区往下刷。
第三轮(进阶突破):窗口函数、综合应用题放在最后。这一轮的目的已经不是"写对",而是"写出最优解"。比如一道题可以用子查询做,也可以用窗口函数做,两种方案都写一遍,并比较一下执行计划的差异。这在面试复盘时非常有价值。
时间上,我建议每天安排1到1.5小时,刷5到8题。太快容易囫囵吞枣,太慢战线拉太长。大约十天左右能完整过完一轮,第二轮查漏补缺会快很多。
4. 练习中的高频报错与逻辑误区速查
4.1 语法层面的常见报错
刷题过程中,绝大多数人都会遇到下面几个报错信息,我先列出来,碰到了不用慌,直接对照解决。
错误1:Column 'emp.ename' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause(SQL Server的报错,MySQL 5.7及以下版本也可能出现类似提示)
这个报错的核心原因就是我前面说的——SELECT中出现了非聚合列,但该列没有出现在GROUP BY中。解决方法就看需求:如果这个列必须出现在结果里,把它加进GROUP BY;如果不需要,把它从SELECT中删掉。不要看到报错就乱改,先搞清楚业务含义。
错误2:子查询返回了多行结果
当你在WHERE后面用=连接一个标量子查询时,如果子查询返回了多行,数据库直接报错。判断标准很简单:如果外层查询需要和子查询结果做逐一匹配,用IN或者EXISTS;只有当子查询明确只返回一行一列时,才能用=。
错误3:NULL比较导致的结果为空
这个不算报错,但比报错更坑人。WHERE sal > NULL的结果是空,WHERE sal <> NULL的结果也是空,因为NULL参与的任何比较都是"未知",不会返回TRUE。判断NULL只能用IS NULL或IS NOT NULL。如果生成的查询结果无故为空,第一反应就去检查是不是把NULL当普通值比较了。
还有一个经常出现的问题是日期格式。在SQL Server里,字符串和日期比较时,隐式转换的规则比较宽松,但如果你插入的数据日期格式不标准,或者用BETWEEN '2023-01-01' AND '2023-12-31'这种写法去过滤日期,很容易把边界日期漏掉或重复算进去。练习时建议统一用YYYY-MM-DD格式,不要用YYYY/MM/DD或者YYYYMMDD。
4.2 逻辑层面的易错点分析
比起语法报错,逻辑错误更隐蔽,产生的查询结果不会报错,但数据不对。
第一个高频逻辑错误是JOIN之后数据翻倍。两张表关联时,如果连接字段的值不是唯一的,结果集就会产生重复行。比如部门表和员工表在deptno上关联,一个部门有10个员工,结果中该部门就会出现10行。这在左连接时尤其不明显——你只知道结果行数多了,但很难一眼发现是哪个连接条件导致的。排查方法我之前提过:先分别SELECT COUNT(*)看两张表的行数,再对比JOIN后的行数,如果后者远大于左表行数,十有八九是连接字段在右表有重复。
第二个高频逻辑错误是WHERE和HAVING的误用。尤其是"先过滤再分组"这种需求,很多初学者习惯把过滤条件全扔进HAVING,逻辑上没错,但性能很差,因为HAVING是在分组完成后才对分组结果进行过滤,数据量大的场景下会白白消耗大量资源。正确的习惯是:能用WHERE过滤的原始行条件,绝对不放到HAVING里;HAVING只用来过滤聚合结果。
第三个逻辑错误是去重语义不清晰。SELECT DISTINCT deptno, job和SELECT deptno, job加GROUP BY deptno, job在结果上几乎一样,但两者语义不同。DISTINCT是对整个结果集去重,GROUP BY是分组聚合(哪怕你不在SELECT中写聚合函数)。50题里如果出现"查询所有不同的部门",很多人会写DISTINCT,也没问题;但如果题目是"查询每个部门的所有不同岗位",用DISTINCT加一列也是对的,可一旦题目要求同时计算岗位数量,就必须用GROUP BY了。练习时要多想一步——这个需求背后是"去重展示"还是"分组统计"。
4.3 从练习阶段就开始规避的性能隐患
在50题练习阶段就建立性能意识,算是一条"超前学习"的经验。虽然练习题量小、性能差异几乎可以忽略,但如果你从一开始就养成以下三个习惯,后面面对千万级数据量的表时会受益无穷。
第一,尽量避免SELECT *。练习时为了看数据方便,SELECT *无可厚非,但正式写查询时,明确列出需要的列既能减少网络传输量,也能让执行计划更高效。另外,在JOIN和子查询中,SELECT *会把所有字段都参与运算,可能拖慢速度。
第二,WHERE条件中的函数包裹会让索引失效。比如WHERE YEAR(hiredate) = 2023,这个写法在功能上没错,但数据库无法直接用hiredate列上的索引,因为索引基于原始值构建。改成WHERE hiredate >= '2023-01-01' AND hiredate < '2024-01-01',既保持同样的语义,又让数据库能够走索引。
第三,多表连接时尽量用表别名。FROM emp e JOIN dept d ON e.deptno = d.deptno这种写法,一方面让SQL更简洁可读,另一方面避免两个表出现同名字段时数据库报"列名不明确"的错误。这不算性能问题,但能省下不少排错时间。
5. 从50题练习到真实面试与工作场景
5.1 面试题与练习题的真实差距
练完50题,你会发现自己已经有能力应对大多数SQL面试的基础环节。但这里我要泼一盆冷水:面试题和练习题的考察深度、维度是有明显差异的,盲目刷完50题就直接去面试,可能还会碰壁。
差异主要体现在三个方面。第一,面试更看重交流过程。面试官让你写SQL时,并不是只看最终结果对不对,他还会追问你"为什么用LEFT JOIN而不是INNER JOIN""如果数据量到百万级别,你的查询还扛得住吗"。这是对分析思路和性能敏感度的考察,单纯把SQL写出来是不够的。
第二,面试题往往有业务背景包装。比如"查询连续登录3天的用户"或者"统计每个品类销售环比增长",这些题目在50题里可能只是抽象的SQL语法问题,但在面试中需要你先拆解业务语义,再翻译成SQL逻辑。这个"业务翻译"能力需要通过额外的场景化练习来补。
第三,手写SQL的熟练度。面试现场没有IDE的自动提示,很多人离开编辑器连最基本的函数名都要想半天。练完50题后,建议你阶段性地做"无提示手写练习"——打开一个空白编辑器,不开自动补全,逼自己把完整的SQL语句从零敲出来。这个过程很痛苦,但效果立竿见影。
5.2 在练习中同步培养优化意识
我建议你在刷50题的中后期,给自己加一个强制要求:每道题写完,至少想一下"还有没有其他写法"。比如同样的查询结果,用子查询能实现,用窗口函数能不能实现?用JOIN能不能实现?这个思维方式对真实工作中应对慢SQL优化特别重要。
前阵子我带一个实习生处理一个慢SQL,需求是查某个用户最近10笔订单。他第一版写的是SELECT * FROM orders WHERE user_id = 123 ORDER BY create_time DESC LIMIT 10,从语法上看完全没问题。但实际跑的时候卡了好几十秒。后来看了执行计划,发现索引用的是user_id,但排序字段create_time没有索引,数据库不得不把所有该用户的订单拿到临时表排序后再取前10条。改成INDEX(user_id, create_time)联合索引后,查询毫秒级返回。
这个案例说明,SQL写对只是第一步,写快才是实战中的核心痛点。练习阶段你可能不会遇到这么大的数据量,但可以提前建立"索引意识"——看到每个WHERE条件、JOIN条件、ORDER BY字段,习惯性地想一想"这个字段该不该有索引"。等真正遇到性能问题,你的直觉会比没有练过的人敏锐得多。
5.3 后续进阶路线怎么走
50题认真刷完后,下一步怎么进阶,取决于你的目标。
如果目标是应付面试,接下来可以专门去刷"SQL面试题"和"SQL大厂真题"。50题打底之后,你会发现自己做这类题目的速度明显提升,需要重点补的是"业务场景翻译"和"边写边讲"的面试表达能力。建议找一个小伙伴一起练,一个出题一个写,写完互相讲解思路,效果比一个人闷头刷好很多。
如果目标是提升实际开发中的SQL能力,我建议把重心转向慢SQL优化和执行计划分析。比如拿一张真实生产环境的表(脱敏后),自己写各种查询,用EXPLAIN(MySQL)或"显示估计的执行计划"(SQL Server)去分析索引使用情况,对比不同写法的执行计划差异。这条路会打开一个全新的世界——你会开始理解数据库是怎么"思考"的,而不是简单地把它当做一个黑盒。
如果你的方向是数据分析和报表开发,那50题之后建议补一下窗口函数的深度应用、行列转换、以及和报表工具(比如Superset这类支持SQL取数的工具)的配合使用。窗口函数做同环比、累计值、移动平均,是数据分析场景的日常操作,50题里涉及的窗口函数只是一个引子,后面需要自己找题目持续强化。
我个人在带人的过程中发现一个规律:能把50题每一道都独立写对、还能讲清楚为什么这么写的同学,后面无论是转数据岗位还是写业务代码,SQL相关的部分基本都不需要人操心。因为这套练习培养的不是某个孤立知识点,而是一整套"看需求→拆解逻辑→选对语法→验证结果"的思维方式。这个思维方式,才是SQL练习的真正价值所在。
