首页 / 资讯中心 / 文章详情

SQL基础教程学习主线:GROUP BY、多表联结与窗口函数实战

SQL基础教程学习主线:GROUP BY、多表联结与窗口函数实战 ★ FEATURED ARTICLE
翻开一本 SQL 入门书绝大多数人会在第三章前后停下来。前面SELECT ... FROM ... WHERE写得挺顺,一到GROUP BY和HAVING就开始发懵,再往后看到子查询套了三层、联结配着聚合一起出现,干脆合上书去刷视频了。这个现象我见过太多次,问题基本不在书,而在读书的姿势——把一本教程当成小说从头翻到尾,却从来没有把书里的示例数据真正敲进自己的电脑里跑一遍。《SQL基础教程》这类定位的书,价值恰恰在于它不炫技。它讲的是 SQL 这门语言里那套几十年没怎么变过的骨架:怎么从一张表里取数、怎么聚合、怎么把两张表对上、怎么在查询里再套查询。这套骨架换到任何数据库产品上都成立,区别只是方言。所以这篇文章我想聊的不是这本书好不好,而是:这本书的知识主线到底长什么样、哪些章节是被大多数人跳过去但其实最值钱的、示例数据该怎么自己搭起来、练习题怎么刷才有用、以及书里讲得比较克制的那些坑在真实工作里是怎么咬人的。适合刚入门 SQL 的人,也适合用了两三年、能写查询但说不清执行顺序的人回头补课。1. 先搞清楚这本书的定位它是能上手干活的阶梯,不是语法字典很多人对入门书的期待是错的,买之前希望它像手册一样随查随用,读完又嫌它太浅。我的看法是:这类书的正确定位是一条从能看懂别人写的查询到能自己拼出一个可用查询的阶梯,全程大约需要 20 到 40 小时的动手时间,而不是 3 小时的通读时间。搞清楚这个定位,你才知道该怎么用它。1.1 三类读者,三种完全不同的读法第一类是零基础转岗的人,比如做运营、做测试、做财务,日常工作里开始需要自己拉数据。这类读者最忌讳的是先学数据库原理再学 SQL。原理当然重要,但顺序反了会直接劝退。我的建议是:跳过所有讲安装配置的长篇大论,直接用一个在线 SQL 环境或者最轻量的本地数据库跑起来,先把前三章的查询写完,回头再补环境细节。动手的反馈来得越快,你越能熬过前面那段枯燥期。第二类是有编程基础、但 SQL 写得零零散散的人。这类人通常已经会写单表查询,卡在联结和子查询上。他们的读法应该反过来:先翻目录,把联结子查询窗口函数这几章挑出来精读,前面的章节当成复习快速过。因为对他们来说,真正的瓶颈不是语法不熟,而是脑子里没有表与表之间怎么建立关系的模型。第三类是把这本书当参考书的人。坦白讲,这个用法效率最低。SQL 的语法细节查官方文档比查任何书都准,书的价值在知识组织方式和练习设计上,不在语法条目上。如果你只想要一份语法速查表,打印两页纸就够了,不必买书。我见过不少某开发者式的学习者,一次性买了三四本 SQL 书,结果每本都停在第五章。原因很简单:书与书之间的知识重叠度极高,同时读三本并不会让你更快,只会让你在三套不同的示例数据之间来回切换,消耗掉本就不多的耐心。选一本,把它跑完,比选三本各读三分之一强十倍。1.2 它明确不解决的问题,这点比宣传语更重要说清楚一本书不做什么,比说它能做什么更有参考价值。这类基础教程通常不会深入讲:性能优化。索引原理、执行计划解读、慢查询定位,这些内容在任何一本入门书里都只是提一嘴。因为讲透它们需要先有真实的业务场景和海量数据,入门阶段根本模拟不出来。数据库运维。备份恢复、主从复制、权限体系、连接池配置,这些属于另一个工种的知识域。业务建模。怎么设计表结构、范式该拆到第几层、什么时候该故意反范式,这是经验活,书里给不出答案。特定产品的方言差异。书里的示例通常绑定某一个数据库产品,换到另一个产品上,日期函数、字符串拼接、分页写法都可能不一样。认清这四条边界之后,你的心态会稳很多。你不会因为读完一本书还写不出高性能查询而焦虑,因为那本来就不在这本书的交付范围内。入门书交付的是能正确表达需求的能力,不是能高效执行的能力,这两件事之间隔着至少半年的真实项目经验。2. 知识主线拆解从单表取数到多表关系的三级跳把这本书的目录抽象一下,它其实在带你完成三次认知跳跃。每一次跳跃都会淘汰一批读者,而每一次跳跃的难点都不在语法本身,而在思维方式。2.1 第一级:单表查询与聚合,语法简单但语义有坑第一级包括SELECT、WHERE、ORDER BY、聚合函数、GROUP BY、HAVING。语法层面这些东西一天就能学完,难的是语义的精确理解。举个最典型的例子:WHERE和HAVING到底有什么区别?很多人背下来的答案是WHERE在分组前过滤,HAVING在分组后过滤。这句话是对的,但背下来不等于会用。真正的理解方式是把它和执行顺序挂钩:执行阶段关键字此时能拿到什么1FROM/JOIN原始行集合2WHERE逐行过滤,看不到聚合结果3GROUP BY行被折叠成组4HAVING按组过滤,能看聚合结果5SELECT计算表达式、起别名6DISTINCT去重7ORDER BY排序,能用别名8LIMIT截断记住这张表,你就同时解决了好几个长期困扰新手的问题:为什么WHERE里不能写聚合函数?因为那时候还没分组。为什么SELECT里起的别名不能在WHERE里用?因为WHERE比SELECT先执行。为什么ORDER BY里可以用别名?因为它排在SELECT后面。这里还有个常见的认知偏差:GROUP BY之后,SELECT列表里只能出现分组列和聚合函数。严格模式下,某些数据库会直接报错;宽松模式下,某些数据库会悄悄取组内第一行的值,不报错但结果是错的。这种能跑但结果不对的情况是最危险的,因为它不会给你任何提示。我建议在本地练习时就把严格模式打开,让错误尽早暴露。聚合里还有一个必须建立直觉的点:COUNT(*)、COUNT(列名)、COUNT(DISTINCT 列名)是三个不同的东西。COUNT(*)数行数,包括全 NULL 的行;COUNT(列名)只数该列非 NULL 的行;COUNT(DISTINCT 列名)数去重后的非 NULL 值。这三个函数在统计报表里混用,是数据对不上账的高频原因之一。2.2 第二级:子查询与联结,真正的分水岭在这里第二级是整本书的分水岭。到这里,读者开始需要在大脑里同时维护两个甚至三个数据集,并且要清楚它们之间是怎么匹配的。这一步过不去的人非常多,而过不去的原因往往不是语法不会,而是没有建立起集合的思维模型。我的经验是:学联结之前,先在纸上画两张表,把每一行写出来,然后手工模拟一下INNER JOIN的结果是什么,LEFT JOIN的结果又是什么,差异在哪几行。这个笨办法看起来很低效,但它建立的是可视化直觉,而直觉一旦形成,后面写多表查询就是条件反射。关于联结,几个必须刻进肌肉记忆的点:INNER JOIN只保留两边都匹配上的行。LEFT JOIN保留左表全部行,右表没匹配上的地方补 NULL。这里有个经典陷阱:如果你在LEFT JOIN之后又在WHERE里对右表的列加了非空条件,那这个LEFT JOIN实际上退化成了INNER JOIN,因为 NULL 不满足任何比较条件。这个 bug 我见过太多次,写的人以为自己在做外连接,跑出来的结果却是内连接。正确做法是把条件写进ON子句,而不是WHERE。子查询这块,书上通常会讲标量子查询、关联子查询、EXISTS、IN。新手最容易混的是关联子查询和普通子查询的区别。普通子查询独立执行一次,结果给外层用;关联子查询依赖外层的每一行,理论上对外层的每一行都要执行一次。理解这一点,你才能明白为什么关联子查询在某些场景下会慢得离谱,以及为什么很多老手更愿意用联结加聚合去改写它。我个人的偏好是:能用联结加聚合表达的,尽量不用关联子查询。不是因为子查询不好,而是因为联结的执行路径更直白,优化器更容易处理,出问题时也更容易定位。当然这不是铁律,某些场景下EXISTS的语义更清晰,尤其在做存在性判断的时候,EXISTS往往比IN更不容易踩 NULL 的坑——因为NOT IN遇到子查询结果里有 NULL 时会返回空集,这个行为坑过无数人。2.3 第三级:窗口函数,从汇总到汇总但不折叠第三级是窗口函数。很多基础教程把它放在偏后的位置甚至附录里,但它其实是从会写 SQL到写得优雅的分界线。窗口函数解决的核心问题是:我想看到明细行,同时也想看到这一行所属分组的汇总值。用GROUP BY做不到,因为分组会把明细折叠掉;用关联子查询能做到,但写法啰嗦、性能也未必好。窗口函数一行就搞定:SELECT order_date, customer_id, amount, SUM(amount) OVER (PARTITION BY customer_id) AS customer_total, ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY amount DESC) AS rn FROM orders;这里PARTITION BY划窗口,ORDER BY决定窗口内的顺序,SUM(...) OVER (...)在每一行上算出该行所属分区的汇总值,同时不减少行数。这个不折叠的特性是它最值钱的地方。三个排序函数必须分清:ROW_NUMBER()严格编号不重复;RANK()并列后跳号(1,1,3);DENSE_RANK()并列后不跳号(1,1,2)。做排行榜的时候选错函数,业务方一眼就能看出来。还有LAG/LEAD用于取上一行/下一行,做同比环比、计算相邻两次操作的时间差,都靠它们。这块内容如果书里讲得比较浅,我建议补一篇官方文档的窗口函数章节,把ROWS/RANGE的窗口框架搞明白,那才是真正容易出错的地方。2.4 被跳得最多、但最该精读的一章:CASE 表达式与 NULL 处理如果只能挑一章反复读,我会挑讲CASE和 NULL 的那一章。原因很实在:真实业务里的 SQL,百分之八十的复杂度都来自条件分支和空值。CASE WHEN的写法看着简单,但它能干的事非常多:行转列、分桶统计、条件聚合、空值替换。比如最典型的行转列:SELECT customer_id, SUM(CASE WHEN status paid THEN amount ELSE 0 END) AS paid_amount, SUM(CASE WHEN status refunded THEN amount ELSE 0 END) AS refunded_amount FROM orders GROUP BY customer_id;这一段代码替代了多少人在应用层写的循环,懂的都懂。而 NULL 的处理更是重灾区:NULL不等于任何值,包括它自己,所以NULL NULL的结果不是真也不是假,而是未知;判断空值必须用IS NULL;COUNT(列)会自动忽略 NULL;算术运算里任何一个操作数是 NULL,结果就是 NULL;COALESCE和NULLIF是两个必须掌握的兜底函数。我见过一个真实的对账问题,查了大半天,最后发现是因为NOT IN的子查询结果里混进了一个 NULL,导致整个条件恒不成立,查询静默返回空集。从那之后,我写NOT IN之前一定会多看一眼子查询里那一列是不是可能为空。3. 把示例跑起来:数据集自己搭,比抄书上的结果截图有用一百倍读 SQL 书最大的效率杀手是看懂了但没敲。书上的查询和结果以截图形式摆在那里,大脑会产生一种我会了的错觉,实际上手一写就发现连表名都记不住。解决办法只有一个:自己搭一套数据。3.1 为什么不建议一上来就装重型图形化客户端新手常见的路径是:先花两小时装一个带界面的数据库客户端,再花一小时连不上,再花一小时找教程配置,热情消耗殆尽。这个过程完全没有必要。我的建议是分两步走。第一步,先用最轻量的方式把 SQL 跑起来,命令行或者一个单文件的嵌入式数据库都行,目标是十分钟内看到第一条SELECT的结果。第二步,等你能独立写出带分组的查询之后,再去折腾正式的数据库和客户端。到那时候你已经知道自己在找什么,踩坑也不会那么痛苦。图形化客户端确实好用,但它有个副作用:它把表结构可视化得太舒服了,导致很多人学不会用information_schema或者\d这类命令去看表。在只能敲命令的环境里(比如线上排查问题),不会看元数据是很被动的。所以我一直建议新手前期多敲命令,把看表结构这件事变成肌肉记忆。选数据库产品这块,我的一般建议是:入门阶段随便选一个,但要知道它的方言边界。常见的选择里,有的产品对标准 SQL 遵循度高、类型系统严格,适合学规范;有的产品生态大、周边工具多,适合找工作。两者都可,关键是别在入门阶段纠结太久——SQL 的核心语法在主流产品之间重合度超过八成,剩下两成方言等你有需要时再查文档。3.2 一套能覆盖全书知识点的最小数据集我通常会自建一套小型电商库来配合练习,三到四张表就够,字段不用多,但要保证能覆盖联结、聚合、子查询、窗口函数这几块。结构大致是这样:-- 客户表 CREATE TABLE customers ( customer_id INTEGER PRIMARY KEY, customer_name VARCHAR(50) NOT NULL, city VARCHAR(50), signup_date DATE NOT NULL ); -- 商品表 CREATE TABLE products ( product_id INTEGER PRIMARY KEY, product_name VARCHAR(80) NOT NULL, category VARCHAR(30) NOT NULL, unit_price DECIMAL(10,2) NOT NULL ); -- 订单头表 CREATE TABLE orders ( order_id INTEGER PRIMARY KEY, customer_id INTEGER NOT NULL, order_date DATE NOT NULL, status VARCHAR(20) NOT NULL ); -- 订单明细表 CREATE TABLE order_items ( order_id INTEGER NOT NULL, product_id INTEGER NOT NULL, quantity INTEGER NOT NULL, unit_price DECIMAL(10,2) NOT NULL, PRIMARY KEY (order_id, product_id) );这四张表的设计是刻意的:customers和orders是一对多,orders和order_items是一对多,order_items和products是多对一。有了这一组关系,你可以把书里几乎所有的联结场景都演练一遍,包括查每个客户最近一次下单时间这种带窗口函数的题目。灌数据这件事,我强烈建议手工写INSERT,不要图省事用脚本生成。手工写的时候你会被迫思考:日期格式对不对?金额用不用小数?状态有哪几种取值?这些思考本身就是学习。而且手工数据量小,你能在脑子里对照着预期结果,查出来的数不对劲能立刻发现。等到了解了数据之后,再写个脚本灌几千行做性能观察也不迟。一个具体的坑:金额字段千万别用浮点类型。浮点数在做汇总的时候会出现精度误差,0.1 0.2不等于0.3这种事在数据库里一样成立。金额一律用定点小数类型,这是行规。3.3 每天十五分钟的手写查询习惯我不太相信周末找两小时集中练的模式,因为 SQL 的熟练度是靠高频短时重复堆出来的。更有效的方式是每天十五分钟,只做一件事:从书里挑一个练习,不看答案,自己写,写完执行,对比结果。这个习惯的价值在于它训练的是从需求到查询的翻译能力,而不是从语法到结果的验证能力。前者是你工作时真正要用的,后者只能在考试里得分。具体做法可以是这样:把书里每章的例题抄到一张纸上,只看要求那一句话,比如查出销售单价高于平均单价的商品,然后关掉书,自己想这个需求该拆成几步。写出来跑一遍,结果对了就往下一题;结果不对就加SELECT *一步步看中间结果。调试 SQL 的核心技巧就是分步验证:先把子查询单独跑一遍看它返回什么,再把外层套上去,而不是把一整坨写完再看结果。4. 练习题到底怎么刷:照着抄十遍不如独立写一遍书后练习题的利用率,基本决定了一个人从这本书里能拿走多少东西。我观察到的现实是:超过一半的人从来没做过练习题;做了的人里,又有一半是看着答案抄的。这两个数字加起来,意味着这本书的实际转化率可能不到三成。4.1 卡住的时候,该不该看答案这个问题我给的答案是:卡住十五分钟以上,就看,但只看第一行思路。SQL 练习的卡点通常只有三类:不知道该用哪种联结、不知道该在哪一层做过滤、不知道聚合该按什么分组。这三类问题看答案的完整代码是没用的,你需要的是一句提示,比如想想用左连接还是内连接这个条件应该放在HAVING还是WHERE。看到提示之后,立刻把答案关掉,自己继续写。真正有害的不是看答案,是看完答案之后产生我懂了的错觉但没有重写。我的硬性规则是:凡是我看过答案的题,必须隔一天再独立重写一遍,而且重写的时候不看任何提示。写得出来才算过,写不出来说明当时那个懂了是假的。4.2 一道题写出三种解法,收获是练习的三倍书上的练习通常只给一种参考答案,但绝大多数查询都可以有至少两三种写法。我的习惯是:每道题写完之后,强迫自己换一种写法再写一遍。比如查出下单次数超过三次的客户名这道题,至少可以这么写:-- 写法一:JOIN GROUP BY HAVING SELECT c.customer_name FROM customers c JOIN orders o ON o.customer_id c.customer_id GROUP BY c.customer_id, c.customer_name HAVING COUNT(*) 3; -- 写法二:子查询 IN SELECT customer_name FROM customers WHERE customer_id IN ( SELECT customer_id FROM orders GROUP BY customer_id HAVING COUNT(*) 3 ); -- 写法三:EXISTS SELECT c.customer_name FROM customers c WHERE EXISTS ( SELECT 1 FROM orders o WHERE o.customer_id c.customer_id GROUP BY o.customer_id HAVING COUNT(*) 3 );三种写法结果应该一样,但执行路径不同。这个练习的真正价值不在于写出三种答案,而在于你开始思考为什么会有三种写法它们在什么情况下表现不同。这种思考积累到一定程度,你看一条慢查询就能大致猜出问题在哪。顺便说一句,写法一里GROUP BY后面跟了两个列,而不是只跟customer_id。这个细节在严格模式下的数据库里是必须的,因为SELECT里出现了customer_name。很多新手在这里被报错拦下来,然后去网上搜为什么 group by 报错,搜到的答案往往是关掉严格模式——这是最糟糕的解决方案。正确的做法是理解规则,而不是关闭检查。4.3 错题本的具体格式,别写成流水账错题本这件事,大部分人的做法是抄一遍正确答案就完事,这基本没有用。有效的错题记录至少要有四栏:字段内容示例题目要求查出每个品类销售额最高的商品我第一版错在哪用了MAX但没分组,结果只返回一行关键卡点没意识到每个品类意味着要PARTITION BY category一句话教训看到每个X中最高这类措辞,先想分组还是窗口第四栏是灵魂。错题本的价值不在于记录错误,而在于把错误压缩成一句能在下次触发提醒的话。积累几十条之后,你会发现自己反复踩的是同几个坑,而这几条教训就是你个人的 SQL 弱点清单。5. 书里讲得克制、但真实工作中天天咬人的几个点基础教程受限于篇幅和受众,有些东西只能点到为止。但这些东西恰恰是新手到熟手之间那段最难跨越的距离。我挑几个最常遇到的展开说。5.1 NULL 的三重陷阱:比较、聚合、排序第一重是比较。NULL参与的任何比较都返回未知,不返回真也不返回假。所以WHERE col x会把col为 NULL 的行漏掉,因为未知不满足条件。想要包含空值,得写成WHERE col x OR col IS NULL。第二重是聚合。除了COUNT(*),几乎所有聚合函数都会忽略 NULL。这会导致一个隐蔽的问题:SUM全是 NULL 的组会返回 NULL 而不是 0,AVG的分母是非 NULL 行的数量而不是总行数。后者尤其坑人,因为算出来的平均值会偏大或偏小,而且没有任何提示。稳妥的做法是用COALESCE兜底,或者在算平均值时显式写出分母。第三重是排序。不同数据库对 NULL 在排序中的位置处理不一样,有的默认排在最前,有的排在最后。如果你的分页列表依赖空值排最后这个假设,换一个数据库产品可能就翻车了。写排序时把 NULL 的位置显式指定出来,是最省心的做法。5.2 分页、日期、字符串:方言差异最集中的三块SQL 的核心语法高度统一,但有三块地方几乎每个数据库产品都有自己的写法:功能常见写法 A常见写法 B注意事项分页LIMIT n OFFSET mOFFSET m ROWS FETCH NEXT n ROWS ONLY深分页性能差,页码越大越慢当前时间NOW()CURRENT_TIMESTAMP注意时区是否带日期加减DATE_ADD(d, INTERVAL 1 DAY)d INTERVAL 1 day单位写法不同字符串拼接CONCAT(a, b)a || b任一操作数为 NULL 时结果行为不同类型转换CAST(x AS INT)x::INT建议统一用标准写法这些差异本身不难,难的是你写的时候不知道自己在用方言。我的做法是:练习阶段就用标准写法,遇到报错再去查方言。同时养成一个习惯,在手边记一份我在用的产品有哪些方言的小抄,写的时候扫一眼。深分页这个问题值得单独说一句。LIMIT 20 OFFSET 100000这种写法,数据库需要先扫描并丢弃前十万行,页码越大越慢。真实的列表页如果允许用户翻到很后面,这里就会成为瓶颈。常见解法是用游标分页,也就是记住上一页最后一行的排序键,下一页从那个键之后开始取:WHERE id 上一页最后一条的id ORDER BY id LIMIT 20。这个技巧在书里通常不会讲,但一旦你的数据量过了百万级,它是必须的。5.3 索引:知道什么时候该关心它,比背原理更有用入门阶段不需要精通索引,但必须建立一个判断:什么样的查询可能会慢。这个判断只需要三条规则就能建立起来。第一条,WHERE里对列做了函数运算或者类型转换,索引大概率失效。比如WHERE DATE(create_time) 2024-01-01这种写法,把函数套在列上,数据库没法直接用索引。改成范围查询create_time 2024-01-01 AND create_time 2024-01-02就能走索引。第二条,组合索引遵循最左前缀。建了(a, b, c)的索引,查询条件里只用b和c是走不上的。这个规则听起来简单,实际排查时经常被忽略。第三条,查询返回的行数占比太高时,走索引可能比全表扫描还慢。因为走索引要先查索引再回表,两次随机 IO 的成本可能超过一次顺序扫描。我给新手的建议是:先不管性能,把查询写对;等数据量上来了,再开始看执行计划。看执行计划这件事本身也是需要练的,但前提是你有真实的数据量。在几百行的练习表上看执行计划,看到的信息基本没有参考价值。5.4 事务:至少要能解释为什么我的更新丢了事务这块,入门书通常只讲到BEGIN/COMMIT/ROLLBACK。但真实工作中最容易出问题的不是这三个命令,而是并发场景下的隔离行为。至少要能解释清楚三种现象:脏读,读到了别人还没提交的数据;不可重复读,同一个事务里两次读同一行结果不一样,因为中间被别人改了;幻读,同一个事务里两次按同样条件查,结果行数变了,因为中间被别人插入了新行。不同的隔离级别分别能防住其中哪几种,这个表值得背下来。更实用的一点是:知道你的数据库默认隔离级别是什么,因为很多莫名其妙的数据不一致最后追下去,都是默认隔离级别和业务假设不匹配。还有一个和事务相关的实操细节:长事务要尽量避免。一个事务开着不提交,会长时间持有锁,还可能阻止其他清理机制正常工作。线上排查时看到某个连接开了三天还没提交,基本可以确定是代码逻辑有问题。6. 这本书啃完之后的三条延伸路线读完一本基础教程,最怕的是不知道下一步干嘛,然后开始漫无目的地刷视频。我的建议是按你的实际工作方向选一条路走深,而不是继续横向铺开。6.1 偏数据分析方向:把窗口函数和报表思维练透如果你日常的产出是报表、看板、给业务方回答问题,那延伸重点应该是窗口函数、复杂聚合、以及从指标定义到查询实现的翻译能力。具体可以这样练:找一份你自己的真实数据(哪怕是记账记录、运动记录),给自己出十个问题,比如每个月的支出环比是多少哪类支出的占比最高连续三个月都有支出的类别有哪些。这三个问题分别对应窗口函数的LAG、占比计算、以及分组后连续性的判断。能把这十个问题全部独立写出来,你的分析型 SQL 就基本够用了。再往深走,需要补的是口径意识。同一个月活跃用户,按登录算和按下单算,数字能差一倍。SQL 只是实现手段,真正难的是把指标定义清楚,这需要你理解业务。6.2 偏后端开发方向:把事务和索引补上如果你是要把 SQL 写进代码里的人,那重点应该转向事务边界、索引设计、以及 ORM 与手写 SQL 的取舍。务实一点的做法是:把自己写过的每一个接口,对应的 SQL 都拿出来过一遍,问三个问题:这个查询走索引了吗?这个事务的范围是不是过大?如果并发量翻十倍,哪里会先出问题?这三个问题能把大部分隐患提前暴露出来。还有一个常被忽略的点:手写 SQL 和 ORM 生成 SQL 的差异。ORM 方便,但它生成的 SQL 有时会出乎意料,尤其是关联查询和N1问题。我的习惯是关键路径上的查询一定要把最终执行的 SQL 打出来看一眼,别想当然。6.3 偏数据平台方向:从会写到会管如果你的方向是数据仓库、数据平台这类工作,那延伸的重点是表设计、分区策略、批量导入导出、以及调度任务的依赖管理。这一块的入门方法我推荐重建一遍:找一套现成的、结构比较规整的公开数据集,自己设计表结构、写导入脚本、建索引、然后跑几个分析查询看性能。整个过程走一遍,你会对设计决策如何影响后续使用有非常具体的感受,这是看任何教程都得不到的。顺带提一句关于这本书的获取方式。很多人在找电子版,我的建议是优先用正规渠道,纸质书或者正规电子版都行。原因不只是合规,更实际的是:这本书的练习题和示例结构是配套设计的,你手上有个能随手翻、能写批注的版本,练习效率会高很多。如果实在只能用别的形式,至少保证自己有一份能随时查的目录和知识点索引,不然回头复习时找东西会非常痛苦。最后分享一个我自己用了很多年的小方法。每次学完一个新知识点,我会用一句话把它写成如果遇到 X,就用 Y,因为 Z的格式,记在一个纯文本文件里。比如:如果要统计每个分组内的排名,就用窗口函数ROW_NUMBER() OVER (PARTITION BY ... ORDER BY ...),因为它不折叠行,而GROUP BY会。这种句式强制你把场景、手段、理由三件事同时写清楚,写不出来就说明还没真懂。一年下来攒一百多条,它就变成了完全属于你自己的那份 SQL 笔记——比任何一本书都更贴合你踩过的坑。
阅读完成 · 觉得有帮助?
咨询建站