公司动态

掌阅秋招数据分析笔试全解析:SQL、Python与业务思维

📅 2026/9/1 5:52:49
掌阅秋招数据分析笔试全解析:SQL、Python与业务思维
1. 考前摸底2023年掌阅秋招数据分析岗笔试到底考什么先说个结论掌阅科技的数据分析岗笔试考察的并不是那种纯理论、纯算法竞赛式的硬核题目而是非常典型的“互联网业务数据分析”风格。整套题做完最大的感受是——它想筛掉的不是不会写代码的人而是没有业务数据思维、拿到问题只会套模板的人。2023年这轮秋招笔试整体分为三大块SQL与数据提取题、Python编程与统计概率题、业务分析与综合开放题。其中还穿插了一些Excel处理类的题目不过比重不大更多是借助Excel考察数据清洗和透视表的功底。整套题目的时间限制是90分钟题量大概在15到20道左右部分题目是选择题但核心的大题集中在一个复杂SQL多表关联两道Python编程题一道业务分析大题。从我复盘后的感觉来看掌阅的笔试有一个非常明显的特点几乎所有题目都挂靠在真实的阅读产品场景上。比如用户阅读时长分析、付费章节转化、会员续费预测、书籍推荐效果评估等等。不是那种上来就给学生信息表让你算平均分的通用题目而是把产品数据模型放在你面前让你像一个真正在网文平台做数据分析的人那样去解题。所以这篇文章我不只讲“考了什么”更想带你拆解每一类题的答题逻辑和踩坑点。如果你是准备投数据分析岗的应届生或者想转行做业务数据分析这篇文章应该能帮你少走不少弯路。2. SQL与数据提取题不是会写 join 就能过2.1 高频考点不是“难语法”而是“业务翻译”掌阅笔试里的SQL题或者说大多数互联网公司数据分析岗笔试里的SQL题难度都不会超过LeetCode中等偏下水平。但为什么很多同学觉得难因为题目给你的不是一张干净的“学生表”而是一堆带业务含义的表你需要先把中文业务问题“翻译”成SQL逻辑。2023年执念那场笔试里SQL大题涉及三张表大致是用户表 user_infouser_id、注册日期 reg_date、设备类型 device_type、渠道来源 channel阅读行为表 read_loguser_id、book_id、阅读起始时间 start_time、阅读时长 read_minutes、阅读章节 chapter_id付费订单表 pay_orderorder_id、user_id、book_id、支付金额 pay_amount、支付时间 pay_time题目大概有三问统计每个渠道的注册用户数以及这些用户中在注册后7天内产生过阅读行为的人数。找出每个用户阅读时长最长的书籍并输出该书籍连续阅读天数大于等于3天的用户。计算付费用户次月续费率的月趋势这里还有一个跨月去重的坑。这三道题分别考察了基础聚合、窗口函数、时间差计算和去重逻辑。没有一道是让你写递归查询或者复杂正则的但每一道都在考“你能不能把这个业务问题落成SQL”。2.2 七天内阅读行为日期比较的逻辑你能一次写对吗第一道的核心是筛选注册后7天内有过阅读记录的用户。很多人的第一反应是 join 两张表然后 where read_time date_add(reg_date, interval 7 day)。这里有一个非常隐蔽的坑阅读行为表的 start_time 是带时分秒的时间戳而注册日期往往是当天零点的时间戳或者纯日期。如果你直接用 read_time reg_date interval 7 day在多天数据的情况下可能把注册当天以前的阅读记录也算进来因为用户的阅读时间可能比注册时间更早。我当时写的解法是select u.channel, count(distinct u.user_id) as reg_user_cnt, count(distinct case when r.user_id is not null then u.user_id end) as read_user_cnt from user_info u left join read_log r on u.user_id r.user_id and r.start_time u.reg_date and r.start_time date_add(u.reg_date, interval 7 day) group by u.channel;关键是把时间过滤条件写在 join 的 on 子句里而不是 where 子句里。为什么因为你如果放到 where 里left join 会先关联再把不符合条件的右表行过滤掉最终效果等于 inner join那些没有阅读记录的用户会被整行丢掉注册用户数就统计错了。这个错误在笔试里很难通过报错暴露出来因为SQL能跑出来只是结果不对。这也是我反复跟学弟学妹强调的SQL题目的自查最重要的是思考“这个条件放 join 还是放 where”。2.3 每本书最长阅读时长窗口函数的基本功第二道题找出每个用户阅读时长最长的书籍。这题如果不知道窗口函数写起来会非常绕。我当时用的方案是 row_number() 按用户分组、按读时间倒序排序select user_id, book_id, max_read_minutes from ( select user_id, book_id, read_minutes, row_number() over (partition by user_id order by read_minutes desc) as rn from read_log ) t where rn 1;这里有个细节如果同一个用户有多本书阅读时长并列第一row_number() 只会随机返回其中一条而 rank() 会返回并列的两条。如果业务需要把所有时长最长的书都输出应该用 rank()。笔试时我随手写了 row_number()后来复盘想想如果要列全用 rank() 更符合“找出最长书籍”的业务语义。不过这里真正容易出错的不是窗口函数本身而是题目中还有一个“连续阅读天数大于等于3天”的条件。我当时的处理是先按 user_id, book_id 计算每天的阅读记录用 date_sub 或 lag 判断连续性生成连续阅读的组号再统计每组的天数。这一步很考验基本功本质上是“连续日期分组”的经典场景。2.4 次月续费率的坑跨月去重你会不会第三道题是统计付费用户次月续费率这题有两个难点一是“次月”的定义二是“去重”。很多人在统计“次月续费”时会犯一个错误如果用户在一个月内多次付费那他在“次月”的付费记录可能会出现多条如果不提前去重分子会被撑大。我当时是这么处理的with pay_month as ( select user_id, date_format(pay_time, %Y-%m) as pay_month, count(distinct pay_order_id) as pay_cnt from pay_order group by user_id, date_format(pay_time, %Y-%m) ) select a.pay_month, count(distinct a.user_id) as active_users, count(distinct b.user_id) as renew_users, count(distinct b.user_id) / count(distinct a.user_id) as renew_rate from pay_month a left join pay_month b on a.user_id b.user_id and b.pay_month date_format(date_add(concat(a.pay_month, -01), interval 1 month), %Y-%m) group by a.pay_month;这个写法虽然能跑但有个问题如果用户在一个月内多次付费虽然在 pay_month 里已经按 user_id month 做了 group by但同一个用户可能在同一月份有多行不会因为 group by 的粒度就是 user_id 月份所以一个用户一个月只有一行去重是没问题的。实际在掌阅的业务场景里“续费”本质上是押下个月的会员费所以更好的做法其实是根据“会员到期日”来计算次月是否重新付费而不是单纯看下单时间。但笔试给的表只有支付时间那我这个做法就是合理的简化方案。答题时如果能主动向面试官说明这个假设会是一个加分点。3. Python编程与概率统计数据岗笔试的第二道分水岭3.1 笔试不是算法岗考的其实是数据分析和数据处理能力掌阅笔试里的Python编程题难度远低于力扣中等题甚至可以说只要你会用 pandas 做过滤、分组、合并就能解决大部分问题。但很多人偏偏栽在这里为什么因为平时刷题刷的都是纯Python列表操作遇到“用pandas处理一个CSV”这种题目反而不知道怎么写。2023年笔试里有一道题是给了一份图书评分数据包含 user_id、book_id、rating、timestamp 四列要求筛选出评分人数不少于100人的书籍计算这些书籍的平均评分并按平均评分降序输出前10本书的书名和平均分。如果这道题你用纯Python写需要自己读CSV、自己数频次、自己排序虽然能写出来但代码量会很大还容易出bug。而用pandas只需要十几行import pandas as pd df pd.read_csv(book_ratings.csv) book_stats df.groupby(book_id)[rating].agg([count, mean]).reset_index() popular_books book_stats[book_stats[count] 100] top10 popular_books.sort_values(mean, ascendingFalse).head(10) print(top10)这个题说白了考的不是算法而是“你熟不熟悉数据分析工具”。如果平时习惯用Excel做所有数据处理这一题就会卡住。所以我建议所有投数据分析岗的同学至少要把 pandas 的 groupby、merge、apply、pivot_table 这几个核心操作练到肌肉记忆。3.2 概率统计不是算正态分布而是算业务概率除了数据处理掌阅笔试还出了几道概率统计题。这些题目不会直接让你推导公式而是包装成业务场景。比如某推荐策略的点击率是5%实际抽样1000次点击率高于6%的概率是多少本质上是要用中心极限定理或者二项分布近似来计算。这题的考点其实在于你是否知道当样本量足够大时二项分布可以用正态分布近似并且能写出均值和方差的表达式。均值是 np方差是 np(1-p)然后用 z (x - mean) / std 查表或者用Python计算。我当时是用 scipy 算的from scipy.stats import norm import math p 0.05 n 1000 mean n * p std math.sqrt(n * p * (1 - p)) z (60 0.5 - mean) / std # 连续性校正 prob 1 - norm.cdf(z) print(prob)注意这个连续性校正很多同学会漏掉。因为二项分布是离散分布而正态分布是连续分布当用正态近似二项分布的时候习惯上会加减0.5做连续性校正。虽然做笔试时不一定要求这么严谨但如果能在答题中体现这一步说明你是真懂统计的而不是背公式。3.3 AB测试的常见陷阱显著性水平、样本量和多重比较另外掌阅笔试还考了一道关于AB测试的题目某次实验设置了3个实验组和1个对照组每组样本量不同实验结果显示其中一组显著优于对照组问是否可以认为该策略有效这道题的陷阱在于多重比较问题。你看同时做3个实验组和1个对照组比本质上是在做3次假设检验。如果每次检验的显著性水平都是0.05那么至少有一次出现假阳性的概率是1 - (0.95)^3约等于14.3%比单次检验的5%高了不少。所以如果不在实验设计阶段做多重比较校正比如Bonferroni校正那么“某个实验组显著”这个结论的可信度是要打折的。回答这类问题时建议按这样的思路去组织先肯定结果表面上有显著性差异再从多重比较的角度说明风险再回答是否需要做样本量校验——如果三组样本量差异太大检验功效也会受影响最后补充实际决策不能只看p值还要看效应量和业务成本。这样的回答结构会让面试官觉得你不是在背知识点而是真的做过AB测试。3.4 连续阅读天数的Python实现数据人应该见过的经典case说回Python题还有一道是给一个用户阅读记录列表每条记录包含 user_id、read_date要求统计每个用户最大连续阅读天数。这其实是SQL连续问题在Python中的变体也是我前面提到SQL那道题的Python版。常规解法是用日期减去行号来生成连续分组的key。Python里可以用 pandas 的 shift 和 cumsum 来实现import pandas as pd df pd.read_csv(read_log.csv) df[read_date] pd.to_datetime(df[read_date]) df df.sort_values([user_id, read_date]).drop_duplicates([user_id, read_date]) df[diff] df.groupby(user_id)[read_date].diff().dt.days df[new_group] ((df[diff] ! 1) | (df[diff].isna())).astype(int) df[group_id] df.groupby(user_id)[new_group].cumsum() df[rank] df.groupby([user_id, group_id]).cumcount() 1 max_days df.groupby(user_id)[rank].max().reset_index()注意这个解法里面有一个关键的坑必须先去重。因为同一天可能有多条阅读记录如果不先去重那么同一天的多次记录会打破连续性判断。这类题的变体在平时做项目时也经常遇到比如计算连续签到天数、连续活跃天数、连续购买天数等。掌握了这个思路之后一通百通。4. 综合分析与业务开放题没有标准答案但要有分析框架4.1 题型特点给一个商业问题要你从数据中找答案掌阅笔试的最后一道大题是开放性的业务分析题题目大概是这样的假设你是掌阅的数据分析师发现近期“男性用户群体的付费转化率下降了10%”请结合数据分析思路描述你的分析过程。这种题没有标准答案但考察的是你的分析框架和业务敏感度。很多应届生拿到题就开始瞎编“可能是因为内容不够吸引男性用户”、“可能是竞品抢走了用户”、“可能是价格太高了”……这些都是猜测不是数据分析。正确的思路应该是先定义问题再拆解问题再找到对应的数据指标再提出分析方法和归因框架。4.2 我建议你用“漏斗拆解维度拆解归因分析”三步法第一步拆漏斗。付费转化率不是一步到位的它背后其实是一条链路曝光 - 点击 - 试读 - 加入书架 - 点击付费 - 支付成功。你要先搞清楚这10%的下降主要集中在哪个环节。如果付费页面的UV没降但支付成功人数降了那问题可能在支付流程如果是试读转化到付费的环节降了那问题可能在内容质量或定价策略。第二步拆维度。转化率下降不是所有用户一起降的而是某些特定用户群体降得更明显。你可以按渠道、按设备类型、按用户新老、按用户活跃度、按书籍类目等维度去拆。比如发现“安卓端新用户转化率下降20%”而iOS端没怎么变那问题的排查范围一下就缩小了。第三步归因分析。到这里才能开始谈可能的原因和验证方法。比如“是不是版本更新导致的支付页兼容问题”那查一下版本发布记录“是不是某个推荐策略导致推荐内容与男性偏好不匹配”那要看推荐策略上线时间和转化率拐点是否重合“是不是暑期结束导致活跃结构变化”那要看新老用户占比是否发生了显著变化。我当时笔试时的回答基本上就是按照这个框架展开的并且补充了一个重要的观点不要一上来就做数据挖掘先看清现象、理清定义、拆解漏斗。分析框架才是分析师的核心竞争力模型和算法只是工具。4.3 分析表达里的“潜台词”要学会用数据指标说话这种业务大题还有一个考察点是你的表达方式。很多同学写“男性用户觉得书不好看”“推荐内容不适合男性”这类主观描述这其实是数据分析里的大忌。数据分析只能回答“是什么”和“为什么”而“是什么”和“为什么”都必须用数据来支撑。所以正确的表达方式是转化率下降10% - 通过漏斗拆解发现是试读转付费环节下降 - 进一步拆维度发现是新用户中男性占比下降 - 结合业务背景发现新上线的推荐策略没有覆盖男性偏好类目 - 建议用AB测试验证。这种写法每一步都有逻辑连接而且每一层的结论都是从上一层数据推导出来的。如果你在笔试中这样答即便没有真实数据支撑面试官也能看出你具备完整的数据分析思维。4.4 掌阅特有的业务分析点网文平台的数据分析特色另外如果你了解掌阅的业务模式在回答这类题时还可以适当提出一些网文平台特有的分析角度比如章节付费转化网文平台的核心付费逻辑是“免费试读前若干章后续章节按章购买或订阅”所以每一章都会有一个付费转化漏斗分析“第几章开始付费流失率最高”是非常有产品价值的数据分析课题。作者维度的贡献度阅读平台的收入高度依赖头部作者和头部书籍分析作者的完读率、付费用户连带率比单纯看单本书的付费转化更重要。阅读时长与付费行为的关系一个用户阅读时长很长但不付费可能是一个“白嫖党”也可能是一个潜在的会员用户需要通过数据建立两者的关联模型。这些点如果你能在开放题里提到至少说明你对掌阅这家公司做了功课而不是一个只会上网搜面经的候选人。这种差异化往往就是笔试里拉开差距的地方。5. 备考经验与考场策略笔试前一周还能做什么5.1 针对性刷题列表不要盲目刷力扣要刷业务SQL我收到很多学弟学妹的私信问“准备数据分析笔试是不是要刷LeetCode”之类的问题。我的建议是不用刷难题刷SQL和pandas才是性价比最高的。LeetCode上完全没有必要刷hard级别的算法题如果你是面试算法岗那另当别论但数据分析岗考SQL的地步基本是medium偏下。我当时考前一周做了这几件事LeetCode数据库题库里的前50道题尤其是那些考窗口函数、分组聚合、日期处理的题用 pandas 跑了一遍Kaggle上一个中小型数据集做了完整的清洗、透视、聚合、可视化的流程把业务分析类的面经题用“四步法”练习了十来道每次都按框架写出分析思路而不是单纯在脑子里过一遍复习了AB测试的样本量计算公式、显著性水平和常见陷阱。这样下来其实不需要太多时间每天2到3小时就能搞定。5.2 笔试现场的时间分配与答题顺序掌阅的笔试是限时的90分钟对大部分人来说是比较紧凑的。我的建议是拿到卷子先花3分钟浏览全部题目不要上来就闷头写。先把那些选择题、基础题快速做掉把大头时间花在SQL和Python编程题上最后留10到15分钟给业务开放题。不过也要注意如果SQL题卡住了不要死磕一道题先跳过做后面的避免出现“一题卡死、满盘皆输”的局面。因为笔试的成绩一般不是看单一题是否满分而是看整体完成度和正确率。另外有些笔试平台不支持本地IDE调试你只能在线写代码所以代码必须写得相对整洁不能依赖调试工具来发现问题。平时训练时就要养成“写完代码后自己逐行读一遍”的习惯。5.3 在线笔试环境注意事项这里分享几个我在实际笔试中踩过的坑大家务必注意提前测试浏览器兼容性。有些笔试系统在Chrome上没问题但在Safari或Edge上可能白屏或者代码高亮失效备好本地IDE。虽然在线平台不能直接跑但你可以把代码先在本地跑通再粘过去注意网络稳定性尽量用有线网络或稳定的Wi-Fi避免因为断网导致答案丢失保持屏幕干净不要开太多无关标签页。虽然大多数笔试平台不强制开摄像头但严谨的公司笔试可能会做屏幕监控不必要的行为容易造成误会。5.4 考后复盘及时总结经验比笔试结果更重要不管笔试结果如何我强烈建议你考后做一次系统性的复盘。把每道题的题干回忆出来然后看自己的答案哪里不完整哪里可以优化哪部分知识存在盲区。比如我考完掌阅这套题就发现自己对“连续日期分组”这个场景还不够熟练于是专门花了两个晚上把所有变体题都刷了一遍。这个经验在后来的其他笔试中帮了我很大的忙。数据分析岗的笔试题目虽然每家公司考察角度不同但核心知识体系是高度相似的。你复盘做得好后面的笔试就会越来越顺。6. 关于笔试的几点额外提醒与个人经验这套笔试做完我的整体感受是相比找一个大而全的面经模板不如脚踏实地把一个题型的底层逻辑盘清楚。第一个提醒不要轻视选择题。很多人觉得选择题分值低随便蒙就行。但数据分析岗的选择题往往不是纯粹的记忆题而是需要你计算或者做逻辑判断题。比如给你一列数据问中位数和平均数的大小关系或者给你一个AB测试结果判断是否存在辛普森悖论。这类题其实很考验基本功如果靠蒙往往会拉低整体分数。第二个提醒写业务分析题时尽量多用“定义先行”。很多同学一上来就分析但没说清楚“付费转化率”到底怎么定义。分子是什么分母是什么时间窗口是什么。不同的人对同一指标的理解可能完全不同如果不加定义你的分析就缺少立足点。在笔试中能主动定义指标其实是一个很强的信号说明你做过真实的数据分析项目知道业务指标不是想当然的。第三个提醒答题时不要只给结论要给出“可落地的后续动作”。数据分析的价值不在于分析本身而在于分析后的行动。所以在回答开放题时除了指出“可能是推荐策略变化导致的”还要进一步说“建议回滚推荐策略并做AB测试验证”“建议对受影响用户做流失预警和触达召回”。这些落地方案会让你的答案听起来更成熟。第四个提醒保持平和心态。笔试只是整个招聘流程的第一关不是说你笔试拿了满分就能进。更重要的是通过笔试准备你其实是在系统梳理自己的数据分析知识体系这本身就是一个非常有价值的学习过程。就算没有拿到面试机会你收获的知识体系也会在后续其他公司的笔试中持续复用。最后再讲一个小技巧提前关注一下掌阅的财报、公开数据报告和App Store榜单排名了解这家公司的业务重点和产品动态。笔试答题时如果能自然地结合公司业务特征比如提到“会员订阅与广告变现的双轮驱动”“免费小说与付费小说的混合模式”很容易在众多候选人中让面试官记住你。这件事不会花太多时间但回报率很高。