对于想进入互联网大厂的数据分析师来说,SQL是面试中必考的硬技能。本文精选了腾讯、字节跳动、阿里巴巴、美团、京东五家大厂的典型SQL面试题,每家公司2-3道,帮助你提前做好准备。
一、腾讯篇
题目1:连续登录天数统计
场景:用户登录表 user_login,包含字段 user_id(用户ID)、login_date(登录日期)。
要求:查询每个用户连续登录的最大天数。
示例数据:
参考答案:
WITH login_with_grp AS ( SELECT user_id, login_date, DATE_SUB(login_date, INTERVAL ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY login_date) DAY ) AS grp FROM user_login)SELECT user_id,grp, COUNT(*) AS continuous_daysFROM login_with_grpGROUP BY user_id, grpORDER BY continuous_days DESCLIMIT 1;
考点解析:
- • 使用
ROW_NUMBER() 窗口函数生成序号 - • 用日期减去序号,连续日期的差值相同,形成分组标识
题目2:分组TopN问题
场景:订单表 orders,包含 user_id、order_id、amount、order_time。
要求:查询每个用户金额最高的前3笔订单。
参考答案:
SELECT user_id, order_id, amount, order_timeFROM ( SELECT user_id, order_id, amount, order_time, ROW_NUMBER() OVER (PARTITION BY user_idORDER BY amount DESC ) AS rn FROM orders) tWHERE rn <= 3;
考点解析:
- •
ROW_NUMBER() 为每个分组内数据排序编号 - • 注意区分
ROW_NUMBER()、RANK()、DENSE_RANK() 的差异
题目3:用户留存率计算
场景:用户注册表 users(user_id, register_date)和用户活跃表 active(user_id, active_date)。
要求:计算每日新增用户的次日留存率、7日留存率。
参考答案:
WITH new_users AS ( SELECT register_date, COUNT(DISTINCT user_id) AS new_user_cnt FROM users GROUP BY register_date),retention AS ( SELECT u.register_date, COUNT(DISTINCT CASE WHEN DATEDIFF(a.active_date, u.register_date) = 1 THEN a.user_id END) AS d1_retained, COUNT(DISTINCT CASE WHEN DATEDIFF(a.active_date, u.register_date) = 7 THEN a.user_id END) AS d7_retained FROM users u LEFT JOIN active a ON u.user_id = a.user_id GROUP BY u.register_date)SELECT n.register_date, n.new_user_cnt, ROUND(r.d1_retained * 100.0 / n.new_user_cnt, 2) AS d1_retention_rate, ROUND(r.d7_retained * 100.0 / n.new_user_cnt, 2) AS d7_retention_rateFROM new_users nJOIN retention r ON n.register_date = r.register_date;
考点解析:
二、字节跳动篇
题目4:行列转换(行转列)
场景:学生成绩表 scores,包含 student_id、subject、score。
要求:将科目从行转为列,显示每个学生的各科成绩。
参考答案:
SELECT student_id, MAX(CASE WHEN subject = '数学' THEN score END) AS math_score, MAX(CASE WHEN subject = '语文' THEN score END) AS chinese_score, MAX(CASE WHEN subject = '英语' THEN score END) AS english_scoreFROM scoresGROUP BY student_id;
考点解析:
- • 使用
CASE WHEN + 聚合函数实现行转列
题目5:中位数计算
场景:员工薪资表 salary(employee_id, salary)。
要求:计算薪资的中位数。
参考答案:
SELECT AVG(salary) AS median_salaryFROM ( SELECT salary, ROW_NUMBER() OVER (ORDER BY salary) AS rn_asc, ROW_NUMBER() OVER (ORDER BY salary DESC) AS rn_desc FROM salary) tWHERE rn_asc BETWEEN rn_desc - 1 AND rn_desc + 1;
考点解析:
- • 奇数条记录取中间值,偶数条记录取中间两个的平均
题目6:漏斗分析
场景:用户行为表 user_actions,包含 user_id、action(步骤:view/click/order/pay)、action_time。
要求:计算从浏览到支付的各环节转化率。
参考答案:
WITH funnel AS ( SELECT user_id, MAX(CASE WHEN action = 'view' THEN 1 END) AS viewed, MAX(CASE WHEN action = 'click' THEN 1 END) AS clicked, MAX(CASE WHEN action = 'order' THEN 1 END) AS ordered, MAX(CASE WHEN action = 'pay' THEN 1 END) AS paid FROM user_actions GROUP BY user_id)SELECT SUM(viewed) AS view_cnt, SUM(clicked) AS click_cnt, SUM(ordered) AS order_cnt, SUM(paid) AS pay_cnt, ROUND(SUM(clicked) * 100.0 / SUM(viewed), 2) AS view_to_click, ROUND(SUM(ordered) * 100.0 / SUM(clicked), 2) AS click_to_order, ROUND(SUM(paid) * 100.0 / SUM(ordered), 2) AS order_to_pay, ROUND(SUM(paid) * 100.0 / SUM(viewed), 2) AS total_conversionFROM funnel;
考点解析:
三、阿里巴巴篇
题目7:累计求和与移动平均
场景:每日销售额表 daily_sales(sale_date, amount)。
要求:计算每日销售额、累计销售额、近7日移动平均。
参考答案:
SELECT sale_date, amount, SUM(amount) OVER (ORDER BY sale_date) AS cumulative_amount, AVG(amount) OVER ( ORDER BY sale_date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW ) AS moving_avg_7dFROM daily_sales;
考点解析:
- •
ROWS BETWEEN 定义窗口范围计算移动平均
题目8:环比/同比增长率
场景:月度销售表 monthly_sales(year_month, sales_amount)。
要求:计算每月销售额的环比增长率和同比增长率。
参考答案:
WITH sales_with_lag AS ( SELECT year_month, sales_amount, LAG(sales_amount, 1) OVER (ORDER BY year_month) AS last_month, LAG(sales_amount, 12) OVER (ORDER BY year_month) AS last_year FROM monthly_sales)SELECT year_month, sales_amount, ROUND((sales_amount - last_month) * 100.0 / last_month, 2) AS mom_growth, ROUND((sales_amount - last_year) * 100.0 / last_year, 2) AS yoy_growthFROM sales_with_lag;
考点解析:
- • 环比(MoM)对比上月,同比(YoY)对比去年同月
题目9:用户分层(RFM模型)
场景:用户消费表 user_transactions(user_id, order_date, amount)。
要求:根据最近消费时间(Recency)、消费频率(Frequency)、消费金额(Monetary)对用户分层。
参考答案:
WITH rfm AS ( SELECT user_id, DATEDIFF(CURRENT_DATE, MAX(order_date)) AS recency, COUNT(DISTINCT order_date) AS frequency, SUM(amount) AS monetary FROM user_transactions WHERE order_date >= DATE_SUB(CURRENT_DATE, INTERVAL 1 YEAR) GROUP BY user_id),rfm_score AS ( SELECT user_id, recency, frequency, monetary, NTILE(5) OVER (ORDER BY recency DESC) AS r_score, NTILE(5) OVER (ORDER BY frequency) AS f_score, NTILE(5) OVER (ORDER BY monetary) AS m_score FROM rfm)SELECT user_id, recency, frequency, monetary, r_score, f_score, m_score, CASE WHEN r_score >= 4 AND f_score >= 4 AND m_score >= 4 THEN '重要价值客户' WHEN r_score >= 4 AND f_score >= 4 THEN '重要保持客户' WHEN r_score >= 4 AND m_score >= 4 THEN '重要发展客户' WHEN f_score >= 4 AND m_score >= 4 THEN '重要挽留客户' ELSE '一般客户' END AS user_segmentFROM rfm_score;
考点解析:
四、美团篇
题目10:时段订单分布
场景:订单表 orders(order_id, order_time, amount)。
要求:统计每小时的订单量和销售额分布。
参考答案:
SELECT HOUR(order_time) AS hour_of_day, COUNT(*) AS order_cnt, SUM(amount) AS total_amount, ROUND(AVG(amount), 2) AS avg_amountFROM ordersWHERE order_time >= DATE_SUB(CURRENT_DATE, INTERVAL 7 DAY)GROUP BY HOUR(order_time)ORDER BY hour_of_day;
考点解析:
题目11:商家销售额排名
场景:订单表 orders(merchant_id, order_id, amount)。
要求:查询销售额Top10的商家,并显示其排名。
参考答案:
WITH merchant_sales AS ( SELECT merchant_id, SUM(amount) AS total_sales, RANK() OVER (ORDER BY SUM(amount) DESC) AS sales_rank FROM orders GROUP BY merchant_id)SELECT merchant_id, total_sales, sales_rankFROM merchant_salesWHERE sales_rank <= 10;
考点解析:
题目12:复购率计算
场景:订单表 orders(user_id, order_id, order_time)。
要求:计算每月的新客数和复购率。
参考答案:
WITH user_first_order AS ( SELECT user_id, DATE_FORMAT(MIN(order_time), '%Y-%m') AS first_month FROM orders GROUP BY user_id),monthly_stats AS ( SELECT DATE_FORMAT(o.order_time, '%Y-%m') AS month, COUNT(DISTINCT o.user_id) AS total_users, COUNT(DISTINCT CASE WHEN u.first_month = DATE_FORMAT(o.order_time, '%Y-%m') THEN o.user_id END) AS new_users FROM orders o JOIN user_first_order u ON o.user_id = u.user_id GROUP BY DATE_FORMAT(o.order_time, '%Y-%m'))SELECT month, total_users, new_users, total_users - new_users AS returning_users, ROUND((total_users - new_users) * 100.0 / total_users, 2) AS repurchase_rateFROM monthly_stats;
考点解析:
五、京东篇
题目13:库存周转天数
场景:商品库存表 inventory(sku_id, date, stock_qty)和销售表 sales(sku_id, date, sale_qty)。
要求:计算每个SKU近30天的平均库存周转天数。
参考答案:
WITH daily_data AS ( SELECT i.sku_id, i.date, i.stock_qty, COALESCE(s.sale_qty, 0) AS sale_qty FROM inventory i LEFT JOIN sales s ON i.sku_id = s.sku_id AND i.date = s.date WHERE i.date >= DATE_SUB(CURRENT_DATE, INTERVAL 30 DAY)),sku_stats AS ( SELECT sku_id, AVG(stock_qty) AS avg_stock, SUM(sale_qty) AS total_sales FROM daily_data GROUP BY sku_id)SELECT sku_id, avg_stock, total_sales, CASE WHEN total_sales = 0 THEN NULL ELSE ROUND(avg_stock * 30 / total_sales, 2) END AS turnover_daysFROM sku_stats;
考点解析:
题目14:异常订单检测
场景:订单表 orders(user_id, order_id, amount, order_time)。
要求:找出疑似刷单的用户(1小时内下单超过5次或单日消费超过平均3倍)。
参考答案:
WITH user_stats AS ( SELECT user_id, DATE(order_time) AS order_date, COUNT(*) AS order_cnt, SUM(amount) AS daily_amount, AVG(amount) AS avg_order_amount FROM orders GROUP BY user_id, DATE(order_time)),hourly_stats AS ( SELECT user_id, DATE_FORMAT(order_time, '%Y-%m-%d %H:00:00') AS hour_slot, COUNT(*) AS hourly_cnt FROM orders GROUP BY user_id, DATE_FORMAT(order_time, '%Y-%m-%d %H:00:00')),avg_stats AS ( SELECT AVG(daily_amount) AS overall_avg_amount FROM user_stats)SELECT DISTINCT u.user_id, '高频下单' AS risk_typeFROM hourly_stats hWHERE h.hourly_cnt > 5UNIONSELECT DISTINCT u.user_id, '异常高额' AS risk_typeFROM user_stats u left join avg_stats a on 1=1WHERE u.daily_amount > a.overall_avg_amount * 3;
考点解析:
面试准备建议
1. 核心知识点
2. 常见考点总结
窗口函数必会:
- •
ROW_NUMBER() / RANK() / DENSE_RANK() —— 排名类问题 - •
LAG() / LEAD() —— 同比环比、前后行对比 - •
SUM() OVER / AVG() OVER —— 累计、移动计算
业务场景必会:
3. 面试技巧
- 1. 先理解业务场景:明确题目要求,不清楚的地方及时提问
- 2. 写出思路再写SQL:先用伪代码或文字描述逻辑
结语
SQL是数据分析师的基本功,大厂面试中SQL考核通常占30%-50%的比重。建议大家在理解这些真题的基础上,多动手练习,形成自己的解题思路。
练习资源推荐:
祝各位面试顺利,早日拿到心仪的大厂offer!
本文作者:鹏哥数个数专注数据分析与职场成长,欢迎关注交流! #互联网大厂 #面试题 #hivesql #sql面试题 #数据分析 #数据分析师 #窗口函数 #腾讯 #京东 #字节 #美团 #阿里巴巴 #SQL面试真题