面试中要求“熟练掌握SQL”

面试中要求"熟练掌握SQL",核心是能独立解决业务场景下的数据提取、清洗、分析、性能优化问题,而非仅记住语法。

不同岗位(数据分析师/开发/数仓工程师)对深度要求略有差异,但通用核心能力可分为以下6个层级,从基础到进阶层层递进:

一、核心基础语法(必掌握,入门门槛) 这是SQL的"基本功",面试官会通过简单手写题验证,比如"查询近7天销售额前10的商品"。

  1. 数据查询(DQL)- 基础:SELECT(别名、去重DISTINCT)、FROM、WHERE(多条件组合AND/OR、范围BETWEEN、模糊匹配LIKE/REGEXP、空值IS NULL); - 排序:ORDER BY(升序/降序、多字段排序); - 限制:LIMIT/OFFSET(分页、取Top N); - 聚合:GROUP BY+聚合函数(COUNT/SUM/AVG/MIN/MAX)、HAVING(分组后过滤,区别于WHERE)。

2.数据操作(DML)- 增:INSERT INTO(单行/多行插入、从查询结果插入); - 改:UPDATE(单表/多表更新,注意WHERE条件避免全表更新); - 删:DELETE(单表/多表删除,TRUNCATE与DELETE的区别)。

3.数据定义(DDL,偏开发/数仓)- 库/表操作:CREATE/DROP/ALTER(建表时指定字段类型、主键/外键/索引、字符集); - 索引:CREATE INDEX(普通索引、唯一索引、联合索引)、DROP INDEX。

二、多表关联与子查询(核心高频,区分"会用"和"熟练") 实际业务数据分散在多张表(比如用户表、订单表、商品表),这是面试重点考察内容。

  1. JOIN系列(必须吃透)- 内连接:INNER JOIN(仅匹配两表交集); - 外连接:LEFT JOIN/RIGHT JOIN/FULL JOIN(保留左/右/两边全部数据,未匹配补NULL); - 交叉连接:CROSS JOIN(笛卡尔积,知道场景和风险); - 特殊:SELF JOIN(自连接,比如查询员工及其直属领导); - 易错点:ON与WHERE的区别、多表连接时的别名规范、避免笛卡尔积。

2.子查询- 分类:标量子查询(返回单个值)、行子查询、列子查询(IN/ANY/ALL)、表子查询(作为临时表); - 场景:比如"查询购买过类目A商品且客单价高于平均值的用户"; - 进阶:关联子查询(CORRELATED SUBQUERY,子查询依赖外部表,比如WHERE EXISTS)。

三、高级函数与数据处理(业务落地能力) 熟练的标志是能通过函数快速处理业务数据,而非依赖下游工具(Excel/Python)。

  1. 字符串函数:CONCAT(拼接)、SUBSTRING(截取)、TRIM(去空格)、REPLACE(替换)、LENGTH(长度);

2.日期函数(高频中的高频): - 基础:DATE_FORMAT(格式化)、DATE_ADD/DATE_SUB(日期加减)、DATEDIFF/TIMESTAMPDIFF(计算日期间隔); - 进阶:YEAR/MONTH/DAY/HOUR(提取时间维度)、STR_TO_DATE(字符串转日期)、处理时区问题;

3.数值函数:ROUND(四舍五入)、CEIL/FLOOR(向上/向下取整)、ABS(绝对值);

4.条件函数: -CASE WHEN(多分支判断,比如"按订单金额分级:高/中/低"); -IF/IFNULL(简单条件、空值替换);

5.**窗口函数(核心区分度,重中之重)**这是"熟练"和"普通"的核心差距,面试官必问,比如: - 排序类:ROW_NUMBER()/RANK()/DENSE_RANK()(比如"取每个部门薪资最高的3人"); - 聚合类:SUM() OVER()/AVG() OVER()(比如"计算累计销售额、移动平均"); - 偏移类:LAG()/LEAD()(比如"查询用户上一次下单时间、环比数据"); - 窗口定义:PARTITION BY(分组)、ORDER BY(窗口内排序)、ROWS/RANGE(窗口范围)。

四、性能优化(体现"深度",偏开发/数仓,分析师也需了解) 不仅能写出SQL,还能写出"高效的SQL",面试官会问"如何优化慢查询":

  1. 索引优化 : - 理解索引原理(B+树)、适合建索引的场景(WHERE/ JOIN/ ORDER BY字段); - 避免索引失效:比如LIKE '%xxx'、函数操作索引字段、隐式类型转换、OR连接非索引字段; 2.查询优化 : - 避免SELECT *,只查需要的字段; - 大表分页优化(比如WHERE id > 10000 LIMIT 10); - 减少子查询嵌套,改用JOIN; - 分批更新/删除大表数据(避免锁表); 3.执行计划: 会看EXPLAIN(执行计划),理解type(访问类型:ALL/ range/ ref/ eq_ref/ const)、key(使用的索引)、rows(扫描行数)、Extra(Using filesort/ Using temporary等异常提示)。 ### 五、事务与锁(偏开发/后端,数仓/分析师了解即可)

1.事务特性(ACID):原子性、一致性、隔离性、持久性;

2.事务隔离级别 :读未提交、读已提交、可重复读、串行化(解决脏读/不可重复读/幻读); 3.锁机制:行锁/表锁、共享锁/排他锁(了解基本概念,避免面试被问倒)。

六、不同SQL方言的差异(适配性) SQL是标准,但不同数据库(MySQL/ PostgreSQL/ Hive/ SQL Server)有方言差异,需掌握目标岗位所用的: - MySQL:LIMIT、IFNULL、TIMESTAMPDIFF; - Hive SQL:LATERAL VIEW(炸裂数组)、CTE(WITH子句)、分区表/分桶表; - SQL Server:TOP、DATEADD、IIF; - PostgreSQL:LIMIT/OFFSET、TO_DATE、数组函数。 ### 面试常见验证方式(附示例)

  1. 手写SQL题:比如"统计每个用户的首单时间、复购率、近30天下单次数";

  2. 优化题:给出一段慢查询SQL,问如何优化;

  3. 场景题:"如何用SQL计算用户留存率(次日/7日/30日)""如何找出连续3天登录的用户";

  4. 窗口函数题:"用SQL实现排名、累计求和、环比分析"。 ### 总结 - 数据分析师:重点掌握基础语法+多表连接+日期/条件/窗口函数+业务场景落地 ,优化了解即可; - 后端/数据库开发:全量掌握,重点加性能优化+事务锁+执行计划 ; - 数仓工程师:全量掌握,重点加DDL+窗口函数+优化+Hive/数仓建模相关SQL 。 核心是:能把业务问题转化为SQL逻辑,写出的SQL简洁、高效、可维护,而非死记语法。

1个月SQL学习计划(数据分析岗定向) **核心目标**:掌握数据分析所需的SQL核心技能,能独立完成业务数据提取、清洗、聚合、分析,应对面试手写题和实操题。 **学习原则**:**每天2-3小时**,**理论+实操结合**,优先掌握高频知识点,跳过偏开发的事务/锁等内容。 **工具准备**:MySQL(免费易上手)+ Navicat/DBeaver(可视化工具),或用LeetCode/SQLZoo在线刷题。

第1周:夯实基础语法,搞定单表查询(入门关键) **目标**:熟练写单表查询语句,理解聚合、过滤、排序逻辑,能解决基础统计需求。

| 天数 | 学习内容 | 实操任务 | 检验标准 | |------|----------|----------|----------|

| Day1 | 1. 数据库/表操作:`CREATE/DROP/ALTER`、`DESC`查看表结构<br>2. 基础查询:`SELECT`(别名、`DISTINCT`)、`FROM`、`WHERE`(多条件`AND/OR`、`BETWEEN`、`LIKE`、`IS NULL`) | 1. 新建测试库,导入3张基础表:用户表(user)、订单表(order)、商品表(product)<br>2. 练习:查询"2025年1月下单且金额>100元"的订单ID | 能独立写出5个不同过滤条件的查询语句,无语法错误 |

| Day2 | 1. 排序与分页:`ORDER BY`(多字段排序)、`LIMIT/OFFSET`<br>2. 聚合函数:`COUNT/SUM/AVG/MIN/MAX`(注意`COUNT(*)`与`COUNT(字段)`区别) | 1. 练习:查询订单表中"销售额最高的前10个订单"<br>2. 练习:统计"每个商品的总销量、平均单价" | 能正确区分`ORDER BY`和`GROUP BY`的位置,聚合函数使用无错 |

| Day3 | 1. 分组查询:`GROUP BY`+`HAVING`(重点:`HAVING`与`WHERE`的区别)<br>2. 常见数值/字符串函数:`ROUND`、`CONCAT`、`SUBSTRING`、`TRIM` | 1. 练习:统计"总销量>100的商品类别"<br>2. 练习:将用户名和手机号拼接为"姓名-手机号"格式 | 能独立写出带`GROUP BY`+`HAVING`的语句,函数能解决字符串/数值处理需求 |

| Day4 | 复习Day1-Day3内容,整理基础语法笔记 | 1. 汇总单表查询高频易错点(如`WHERE`后不能用聚合函数)<br>2. 刷SQLZoo **SELECT篇** 1-15题 | 能快速写出任意单表统计需求的SQL |

| Day5-Day7 | 巩固提升:每天刷10道单表查询题 | 推荐刷题平台:<br>1. LeetCode 数据库题库 **简单题**(前20道)<br>2. SQLZoo **SELECT from WORLD** 章节 | 正确率≥90%,每题耗时≤5分钟 |

第2周:攻克多表关联,掌握子查询(核心重点) **目标**:熟练使用`JOIN`系列连接多表,能写各类子查询,解决跨表分析需求(数据分析岗高频考点)。

| 天数 | 学习内容 | 实操任务 | 检验标准 | |------|----------|----------|----------|

| Day8 | 1. 多表关联基础:`INNER JOIN`、`LEFT JOIN`、`RIGHT JOIN`(重点:`ON`的作用)<br>2. 自连接(`SELF JOIN`)场景:如"查询员工及其直属领导" | 1. 练习:用`LEFT JOIN`关联用户表和订单表,查询"每个用户的下单次数"(含未下单用户)<br>2. 练习:用自连接查询"订单金额高于自身平均金额的订单" | 能区分`INNER JOIN`和`LEFT JOIN`的结果差异,自连接能理清表别名逻辑 |

| Day9 | 1. 复杂多表连接:3表及以上关联(如user→order→product)<br>2. 子查询基础:标量子查询、列子查询(`IN/ANY/ALL`) | 1. 练习:关联3张表,查询"每个用户购买的商品类别及数量"<br>2. 练习:查询"购买过商品A的用户列表"(用子查询实现) | 3表连接语句无语法错误,子查询能替代部分`JOIN`场景 |

| Day10 | 1. 表子查询(子查询作为临时表,`AS`别名)<br>2. 关联子查询:`WHERE EXISTS`(重点:子查询依赖外部表) | 1. 练习:用表子查询统计"每个月的订单总数"<br>2. 练习:查询"存在重复下单的用户"(用`EXISTS`实现) | 能独立写出带表子查询的语句,理解`EXISTS`的高效性 |

| Day11 | 复习Day8-Day10内容,整理多表连接/子查询笔记 | 1. 汇总`JOIN`系列易错点(如`LEFT JOIN`后用`WHERE`过滤会变成`INNER JOIN`)<br>2. 对比子查询和`JOIN`的适用场景 | 能快速判断业务需求该用`JOIN`还是子查询 |

| Day12-Day14 | 巩固提升:每天刷10道多表查询题 | 推荐刷题平台:<br>1. LeetCode 数据库题库 **简单-中等题**(20-40道)<br>2. SQLZoo **JOIN篇** 全章节 | 正确率≥85%,能解释每段SQL的执行逻辑 |

第3周:吃透窗口函数,玩转日期处理(区分度考点) **目标**:掌握窗口函数核心用法,熟练处理日期维度分析,能完成复杂业务统计(面试加分项)。

| 天数 | 学习内容 | 实操任务 | 检验标准 | |------|----------|----------|----------|

| Day15 | 1. 窗口函数基础:`OVER()`子句、`PARTITION BY`(分组)、`ORDER BY`(窗口内排序)<br>2. 排序类窗口函数:`ROW_NUMBER()`/`RANK()`/`DENSE_RANK()`(重点区分三者差异) | 1. 练习:查询"每个商品类别下销量最高的3个商品"<br>2. 练习:给订单表按金额排序并生成排名 | 能正确区分3种排序函数的结果,`PARTITION BY`使用无误 |

| Day16 | 1. 聚合类窗口函数:`SUM() OVER()`/`AVG() OVER()`(累计求和、移动平均)<br>2. 偏移类窗口函数:`LAG()`/`LEAD()`(前后值获取) | 1. 练习:计算"每月的累计销售额"<br>2. 练习:查询"每个用户的上一次下单时间" | 能写出累计统计和环比分析的SQL,理解`ROWS/RANGE`窗口范围 |

| Day17 | 1. 日期函数(数据分析高频):`DATE_FORMAT`、`DATE_ADD`/`DATE_SUB`、`DATEDIFF`/`TIMESTAMPDIFF`<br>2. 时间维度拆解:`YEAR`/`MONTH`/`WEEK`/`DAY` | 1. 练习:统计"近7天/近30天的订单量"<br>2. 练习:计算"每个订单的下单时间距离用户注册时间的天数" | 能处理任意日期筛选和计算需求,无日期格式错误 |

| Day18 | 1. 条件函数:`CASE WHEN`(多分支判断,核心业务工具)<br>2. 综合练习:窗口函数+日期函数+多表连接 | 1. 练习:按订单金额分级(0-100:低,100-500:中,>500:高)<br>2. 练习:查询"每个用户的首单时间、复购次数" | 能独立写出带`CASE WHEN`的复杂统计语句 |

| Day19-Day21 | 巩固提升:每天刷5道窗口函数+日期处理综合题 | 推荐刷题平台:<br>1. LeetCode 数据库题库 **中等题**(窗口函数专题)<br>2. 牛客网 SQL专项练习 **进阶篇** | 能解决"排名、累计、环比、留存"等分析需求 |

第4周:综合实战+面试冲刺(胜任岗位关键) **目标**:整合所有知识点,完成实战项目,掌握面试技巧,能应对数据分析岗SQL面试。

| 天数 | 学习内容 | 实操任务 | 检验标准 | |------|----------|----------|----------|

| Day22 | 1. SQL性能优化(数据分析岗必备基础):<br> - 索引原理:适合建索引的字段(`WHERE`/`JOIN`/`ORDER BY`)<br> - 避免索引失效的场景(`LIKE '%xxx'`、函数操作索引字段)<br> - 执行计划:`EXPLAIN`关键字(看懂`type`/`key`/`Extra`字段) | 1. 给测试表的高频查询字段建索引,对比查询速度<br>2. 用`EXPLAIN`分析慢查询SQL的问题 | 能说出3个索引失效的场景,会用`EXPLAIN`优化简单慢查询 |

| Day23-Day24 | 综合实战项目:模拟数据分析业务需求 | 项目需求(任选其一):<br>1. **用户行为分析**:统计用户留存率(次日/7日/30日)、复购率、客单价<br>2. **销售分析**:统计各区域/品类销售额、TOP商品、环比增长率 | 能独立写出完整的分析SQL,输出可直接用于报表的数据 |

| Day25-Day26 | 面试高频题专项突破 | 重点刷以下类型题:<br>1. 留存率计算(用`LEFT JOIN`+日期函数)<br>2. 连续登录用户查询(用窗口函数+`DATEDIFF`)<br>3. 去重统计(`COUNT(DISTINCT)`优化) | 能在10分钟内写出留存率/连续登录的SQL |

| Day27-Day28 | 错题复盘+知识点查漏补缺 | 1. 整理前3周的错题本,重新做一遍错误题<br>2. 补充学习目标岗位的SQL方言差异(如Hive SQL的`LATERAL VIEW`) | 错题正确率≥95%,了解目标公司使用的数据库特性 |

| Day29-Day30 | 模拟面试+简历准备 | 1. 找朋友进行SQL手写题模拟面试(每题限时10分钟)<br>2. 整理简历中的SQL项目经验,突出"用SQL解决了什么业务问题" | 能流畅讲解SQL的执行逻辑,面试题正确率≥90% | ## 学习小贴士 1. **实操优先**:不要只背语法,每学一个知识点就立刻写SQL验证,推荐导入真实业务数据集(如电商订单数据)练习。 2. **错题本很重要**:把写错的SQL和错误原因记录下来,比如"`LEFT JOIN`后用`WHERE`过滤导致数据丢失",避免重复踩坑。 3. **针对性刷题**:数据分析岗重点刷**统计、排序、累计、留存**相关题目,不用纠结偏开发的存储过程/触发器。 是否需要我为你整理一份**数据分析岗SQL面试高频手写题清单**,方便你最后冲刺练习?

数据分析岗SQL面试高频手写题清单 这份清单覆盖**单表统计、多表关联、窗口函数、日期分析、业务场景**五大核心模块,是数据分析岗面试的高频考点,建议每题限时 **10-15分钟** 独立完成,重点理解解题思路而非死记答案。 ### 一、 单表查询与基础统计(入门必过) 1. 现有订单表 `orders`(字段:`order_id`, `user_id`, `order_amount`, `order_date`, `pay_status`),统计 **2025年每个月的订单总数、总销售额、平均订单金额**,结果按月份升序排列。 2. 基于 `orders` 表,查询 **2025年第二季度(4-6月)支付成功(`pay_status=1`)且订单金额>500元** 的订单数量。 3. 现有用户表 `users`(字段:`user_id`, `user_name`, `gender`, `register_date`),统计 **男性和女性的用户数量**,要求列名显示为 `性别`、`用户数`。 4. 基于 `orders` 表,找出 **订单金额最高的前10个订单**,若金额相同则按下单时间降序排列。 5. 基于 `users` 表,统计 **2025年每个注册周的新增用户数**(周数从1到52)。

二、 多表关联查询(核心高频) 现有三张表: - `users`(`user_id`, `register_date`) - `orders`(`order_id`, `user_id`, `order_amount`, `order_date`, `product_id`) - `products`(`product_id`, `product_name`, `category`) 1. 查询 **每个用户的用户名、注册时间、累计下单次数、累计消费金额**,包含未下单的用户(显示为0)。 2. 查询 **每个商品类别的名称、总销量、总销售额**,结果按总销售额降序排列。 3. 查询 **购买过"手机"类商品的用户列表**,要求去重,显示用户ID和注册时间。 4. 查询 **2025年5月下单且购买的商品包含"耳机"的订单信息**,显示订单ID、用户ID、订单金额、下单时间。 5. 统计 **每个用户的首单时间和首单金额**,首单定义为用户最早的下单记录。

三、 窗口函数专项(区分度考点) 基于订单表 `orders`(`order_id`, `user_id`, `order_amount`, `order_date`) 1. 给每个用户的订单按 **下单时间升序排序并生成订单序号**,显示用户ID、订单ID、下单时间、订单序号。 2. 查询 **每个用户订单金额最高的前2笔订单**,若金额相同则取最新的一笔。 3. 计算 **2025年每月的累计销售额**,显示月份、当月销售额、累计销售额。 4. 查询 **每个订单的上一笔订单金额和下一笔订单金额**,显示订单ID、订单金额、上一笔金额、下一笔金额。 5. 找出 **连续3天及以上有下单记录的用户**,显示用户ID和连续下单的天数。

四、 日期与业务分析(实战场景) 1. **用户留存率计算**:基于 `users` 和 `orders` 表,计算 **2025年5月1日注册用户的次日留存率、7日留存率**。 > 次日留存:注册第2天有下单的用户数 / 5月1日总注册用户数 2. **复购率计算**:统计 **2025年第二季度的用户复购率**,复购用户定义为下单次数≥2次的用户。 3. **客单价分层**:基于 `orders` 表,按订单金额将用户分为3层:低(≤100)、中(101-500)、高(>500),统计各层级的用户数和占比。 4. **环比增长率计算**:计算 **2025年每个月的销售额环比增长率**,环比增长率 = (本月销售额 - 上月销售额) / 上月销售额 * 100%。 5. **活跃用户统计**:定义活跃用户为"近30天内有下单记录",统计 **2025年6月30日的活跃用户数**。

五、 易错与优化类(进阶加分) 1. 现有SQL:`SELECT * FROM orders WHERE DATE(order_date) = '2025-05-01'`,请说明该SQL的性能问题并给出优化方案。 2. 如何优化 `COUNT(DISTINCT user_id)` 在大表中的查询效率? 3. 用SQL实现:查询 **订单金额大于该用户平均订单金额的所有订单**。 --- 是否需要我为你提供**其中5道高频题的详细解题思路和参考答案**,帮你快速掌握解题技巧?

5道高频SQL面试题(详细解题思路+参考答案) 以下选取**留存率、连续登录、首单统计、累计销售额、客单价分层** 5道最核心的面试题,覆盖日期处理、窗口函数、多表关联等核心考点,附「思路拆解+SQL答案+易错点」,帮你吃透解题逻辑。

题目1:用户次日/7日留存率计算(日期分析+多表关联) #### 题目描述 基于 `users`(`user_id`, `register_date`)和 `orders`(`order_id`, `user_id`, `order_date`)表,计算2025年5月1日注册用户的**次日留存率、7日留存率**。 - 次日留存:注册第2天(2025-05-02)有下单的用户数 / 5月1日总注册用户数 - 7日留存:注册后7天内(2025-05-01至2025-05-08)有下单的用户数 / 5月1日总注册用户数

解题思路 1. **第一步**:筛选出2025-05-01注册的用户(基础筛选); 2. **第二步**:关联订单表,判断这些用户是否在留存时间内下单(日期差计算); 3. **第三步**:统计留存用户数和总注册用户数,计算留存率(注意分母不能为0)。

参考答案(MySQL) ```sql -- 第一步:先筛选5月1日注册的用户,作为基础表 WITH register_users AS ( SELECT user_id FROM users WHERE DATE(register_date) = '2025-05-01' ), -- 第二步:统计留存用户数 retention_stats AS ( SELECT -- 统计次日留存用户数:下单日期=注册次日 COUNT(DISTINCT CASE WHEN DATEDIFF(order_date, register_date) = 1 THEN u.user_id END) AS next_day_retention, -- 统计7日留存用户数:下单日期在注册后1-7天(含) COUNT(DISTINCT CASE WHEN DATEDIFF(order_date, register_date) BETWEEN 1 AND 7 THEN u.user_id END) AS seven_day_retention, -- 总注册用户数 COUNT(DISTINCT u.user_id) AS total_register FROM register_users u LEFT JOIN orders o ON u.user_id = o.user_id ) -- 第三步:计算留存率(保留2位小数) SELECT total_register, next_day_retention, seven_day_retention, ROUND(next_day_retention / total_register * 100, 2) AS next_day_retention_rate, ROUND(seven_day_retention / total_register * 100, 2) AS seven_day_retention_rate FROM retention_stats; ``` #### 易错点 1. 留存率分母是「注册总用户数」,不是「有下单的用户数」; 2. 日期差计算:`DATEDIFF(结束日期, 开始日期)`,注意顺序(比如次日留存是`order_date - register_date = 1`); 3. 必须用`LEFT JOIN`,否则会漏掉"注册但未下单"的用户(导致分母偏小)。

题目2:找出连续3天及以上有下单记录的用户(窗口函数+日期差) #### 题目描述 基于订单表 `orders`(`order_id`, `user_id`, `order_date`),找出连续3天及以上有下单记录的用户,显示用户ID和连续下单的天数。

解题思路 1. **第一步**:对每个用户的下单日期去重(避免同一天多次下单干扰),并按日期排序; 2. **第二步**:用窗口函数`ROW_NUMBER()`给每个用户的下单日期编序号; 3. **第三步**:计算「下单日期 - 序号」,连续日期的结果会相同(核心技巧); 4. **第四步**:按用户+相同结果分组,统计连续天数,筛选≥3天的用户。

参考答案(MySQL) ```sql -- 第一步:用户下单日期去重并排序 WITH user_order_dates AS ( SELECT user_id, DATE(order_date) AS order_dt, -- 只保留日期部分 ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY DATE(order_date)) AS rn FROM orders GROUP BY user_id, DATE(order_date) -- 去重:同一天多次下单算1天 ), -- 第二步:计算日期差,连续日期的dt_diff相同 user_continuous AS ( SELECT user_id, order_dt, rn, DATE_SUB(order_dt, INTERVAL rn DAY) AS dt_diff -- 核心:连续日期的dt_diff一致 FROM user_order_dates ), -- 第三步:统计每个用户的连续天数 continuous_stats AS ( SELECT user_id, dt_diff, COUNT(*) AS continuous_days FROM user_continuous GROUP BY user_id, dt_diff HAVING COUNT(*) >= 3 -- 筛选连续≥3天的记录 ) -- 第四步:输出最终结果(去重用户,取最大连续天数) SELECT user_id, MAX(continuous_days) AS max_continuous_days FROM continuous_stats GROUP BY user_id; ``` #### 易错点 1. 未对下单日期去重:比如用户一天下3单,会被误判为3天; 2. 窗口函数忘记`PARTITION BY user_id`:会给所有用户的日期统一编号,导致逻辑错误; 3. 日期差计算错误:需用`DATE_SUB`而非直接减数字。

题目3:统计每个用户的首单时间和首单金额(窗口函数+排序) #### 题目描述 基于订单表 `orders`(`order_id`, `user_id`, `order_amount`, `order_date`),统计每个用户的首单时间(最早下单时间)和首单金额,包含未下单的用户(需关联`users`表:`user_id`, `user_name`)。

解题思路 1. **第一步**:用窗口函数`ROW_NUMBER()`给每个用户的订单按时间升序排序; 2. **第二步**:筛选出每个用户排序为1的订单(首单); 3. **第三步**:左关联用户表,补充未下单用户的信息(首单时间/金额显示为NULL)。

参考答案(MySQL) ```sql -- 第一步:给每个用户的订单按时间排序,标记首单 WITH user_order_rn AS ( SELECT user_id, order_date, order_amount, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY order_date) AS rn FROM orders ) -- 第二步:关联用户表,统计首单信息 SELECT u.user_id, u.user_name, -- 首单时间:rn=1的订单日期 MAX(CASE WHEN o.rn = 1 THEN o.order_date END) AS first_order_date, -- 首单金额:rn=1的订单金额 MAX(CASE WHEN o.rn = 1 THEN o.order_amount END) AS first_order_amount FROM users u LEFT JOIN user_order_rn o ON u.user_id = o.user_id GROUP BY u.user_id, u.user_name; ``` #### 简化写法(不用窗口函数) ```sql SELECT u.user_id, u.user_name, MIN(o.order_date) AS first_order_date, -- 关联首单日期取金额 (SELECT order_amount FROM orders WHERE user_id = u.user_id AND order_date = MIN(o.order_date) LIMIT 1) AS first_order_amount FROM users u LEFT JOIN orders o ON u.user_id = o.user_id GROUP BY u.user_id, u.user_name; ``` #### 易错点 1. 未处理"用户有多个首单(同一时间下单)":用`LIMIT 1`或`MAX/MIN`避免返回多条; 2. 忘记左关联用户表:导致未下单用户被过滤; 3. 用`RANK()`替代`ROW_NUMBER()`:若同一用户同一时间多单,`RANK()`会生成多个1,需额外处理。

题目4:计算2025年每月的累计销售额(窗口函数+聚合) #### 题目描述 基于订单表 `orders`(`order_id`, `order_amount`, `order_date`),计算2025年每个月的销售额及累计销售额,结果按月份升序排列。 #### 解题思路 1. **第一步**:按月份统计当月销售额(基础聚合); 2. **第二步**:用聚合类窗口函数`SUM() OVER()`计算累计销售额(窗口范围为"从开始到当前行")。

参考答案(MySQL) ```sql -- 第一步:统计每月销售额 WITH monthly_sales AS ( SELECT MONTH(order_date) AS month, -- 提取月份 SUM(order_amount) AS monthly_amount FROM orders WHERE YEAR(order_date) = 2025 -- 筛选2025年 GROUP BY MONTH(order_date) ) -- 第二步:计算累计销售额 SELECT month, monthly_amount, -- 累计销售额:按月份排序,累加所有之前的月份 SUM(monthly_amount) OVER (ORDER BY month) AS cumulative_amount FROM monthly_sales ORDER BY month; ``` #### 进阶:显示完整月份(含销售额为0的月份) ```sql -- 生成1-12月的虚拟表 WITH months AS ( SELECT 1 AS month UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL SELECT 12 ), -- 统计2025年每月销售额 monthly_sales AS ( SELECT MONTH(order_date) AS month, COALESCE(SUM(order_amount), 0) AS monthly_amount FROM orders WHERE YEAR(order_date) = 2025 GROUP BY MONTH(order_date) ) -- 关联虚拟表,补充销售额为0的月份 SELECT m.month, COALESCE(ms.monthly_amount, 0) AS monthly_amount, SUM(COALESCE(ms.monthly_amount, 0)) OVER (ORDER BY m.month) AS cumulative_amount FROM months m LEFT JOIN monthly_sales ms ON m.month = ms.month ORDER BY m.month; ``` #### 易错点 1. 累计销售额未排序:`OVER()`中必须加`ORDER BY month`,否则累计逻辑错误; 2. 忽略销售额为0的月份:需用虚拟表生成12个月,左关联补0; 3. 未筛选年份:导致跨年度数据干扰。

题目5:客单价分层统计(CASE WHEN+聚合) #### 题目描述 基于订单表 `orders`(`order_id`, `user_id`, `order_amount`),按订单金额将用户分为3层: - 低客单:≤100元 - 中客单:101-500元 - 高客单:>500元 统计各层级的用户数、订单数、总销售额及用户占比。

解题思路 1. **第一步**:用`CASE WHEN`给每个订单标记客单层级; 2. **第二步**:按层级聚合,统计用户数(去重)、订单数、总销售额; 3. **第三步**:计算用户占比(各层级用户数/总用户数)。

参考答案(MySQL) ```sql -- 第一步:标记客单层级,统计基础指标 WITH level_stats AS ( SELECT -- 客单层级 CASE WHEN order_amount <= 100 THEN '低客单' WHEN order_amount BETWEEN 101 AND 500 THEN '中客单' ELSE '高客单' END AS customer_level, user_id, order_amount FROM orders ), -- 第二步:按层级聚合 agg_stats AS ( SELECT customer_level, COUNT(DISTINCT user_id) AS user_count, -- 层级用户数 COUNT(*) AS order_count, -- 层级订单数 SUM(order_amount) AS total_sales, -- 层级总销售额 (SELECT COUNT(DISTINCT user_id) FROM orders) AS total_user -- 总用户数 FROM level_stats GROUP BY customer_level ) -- 第三步:计算用户占比 SELECT customer_level, user_count, order_count, total_sales, ROUND(user_count / total_user * 100, 2) AS user_ratio FROM agg_stats ORDER BY -- 按层级排序(低→中→高) CASE customer_level WHEN '低客单' THEN 1 WHEN '中客单' THEN 2 ELSE 3 END; ``` #### 易错点 1. 用户数未去重:用`COUNT(DISTINCT user_id)`而非`COUNT(user_id)`(避免同一用户多单重复统计); 2. 层级边界错误:比如将100元归为中客单,需严格匹配题目要求; 3. 占比计算错误:分母是"总用户数",不是"层级用户数之和"(避免遗漏未下单用户)。 --- 如果需要其他题目的解题思路,或者想针对某道题的优化方式深入探讨(比如如何简化SQL、提升查询效率),可以告诉我。

相关推荐
麦聪聊数据5 小时前
Web 原生架构如何重塑企业级数据库协作流?
数据库·sql·低代码·架构
零售ERP菜鸟7 小时前
范式革命:从“信息化”到“数字化”的本质跃迁
大数据·人工智能·职场和发展·创业创新·学习方法·业界资讯
发现一只大呆瓜7 小时前
虚拟列表:支持“向上加载”的历史消息(Vue 3 & React 双版本)
前端·javascript·面试
Apple_羊先森8 小时前
ORACLE数据库巡检SQL脚本--19、磁盘读次数最高的前5条SQL语句
数据库·sql·oracle
千寻girling8 小时前
Koa.js 教程 | 一份不可多得的 Node.js 的 Web 框架 Koa.js 教程
前端·后端·面试
程序员清风8 小时前
北京回长沙了,简单谈谈感受!
java·后端·面试
网络安全-杰克9 小时前
2026面试自动化测试面试题【含答案】
自动化测试·软件测试·面试·职场和发展
l1t10 小时前
DeepSeek总结的PostgreSQL的GPT推理SQL移植到DuckDB的性能优化方法
sql·gpt·postgresql
努力学算法的蒟蒻10 小时前
day79(2.7)——leetcode面试经典150
算法·leetcode·职场和发展
CodeSheep程序羊11 小时前
拼多多春节加班工资曝光,没几个敢给这个数的。
java·c语言·开发语言·c++·python·程序人生·职场和发展