高频Sql面试题目及答案和解答思路
第一部分:基础实战题(查询 / 分组 / 去重)
1.查询最近 30 天下单的用户数(去重)
orders(id, user_id, amount, created_at)
写出 SQL,统计最近 30 天内有下单的“独立用户总数”。
思路: . 使用 DATE_SUB 函数 . COUNT(DISTINCT user_id)
SELECT COUNT(DISTINCT user_id) AS user_count
FROM orders
WHERE created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY);2. 查询每个用户的最新一笔订单
orders(id, user_id, amount, created_at)
给定订单表,返回每个 user_id 最新的订单记录(整行数据)。
思路:
可以使用 JOIN + MAX(created_at) 的子查询方式,也可以使用窗口函数。MySQL 8 后窗口函数基本是标配考点
子查询
select a.*
from orders a
JOIN (
select user_id, max(created_at) max_created_at from orders GROUP BY user_id
) b on a.user_id=b.user_id and a.created_at=b.max_created_at窗口函数
SELECT *
FROM (
SELECT o.*,
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at DESC) AS rn
FROM orders o
) t
WHERE rn = 1;3. 查询下单金额大于用户平均订单金额的订单
思路:
使用 JOIN + AVG(amount) 的子查询方式
SELECT o.*
FROM orders o
JOIN (
SELECT user_id, AVG(amount) AS avg_amount
FROM orders
GROUP BY user_id
) t ON o.user_id = t.user_id
WHERE o.amount > t.avg_amount;4. 查询连续下单 3 天以上的用户
表中只有 created_at(日期),判断用户是否连续 3 天有订单。
5. 查询本周每天的订单量,没有订单的日期也要显示 0
要求:返回一周 7 天的完整统计(date, count),缺的日期补 0。
第二部分:中级实战(多表关联 / 聚合 / 复杂条件)
6. 查询某用户的“未支付订单金额总和”
order(id, user_id, status, amount)
status: 0-待支付 1-已支付
用户 9527 目前所有未支付订单的金额总和是多少?
—
7. 查询每个品类下销量最高的商品(Top1)
category(id, name) product(id, category_id, name) order_item(id, product_id, quantity)
找出每个 category 对应“销量最高”的 product。
窗口函数必须会。
—
8. 查询 2024 年每个月的 GMV(成交额)
要求返回 2024 年 1~12 月,哪怕某月是 0。
—
9. 统计每个用户的下单金额区间(0~100、100~500、500+)
类似电商用户分层,写 SQL 得到用户处于哪个金额段。
—
10. 查询“只买过一次”的用户名单
用户 lifetime 只有一单的 user_id。
第三部分:进阶实战(窗口函数 / 反复过滤 / 子查询)
11. 查询用户最近一次下单距今多少天
now() - 用户最后一单 created_at → 返回天数。
—
12. 查询某用户前 3 次订单(按金额排序)
user_id = X,amount 降序,取 Top3。
—
13. 查询每个用户近 5 次订单的平均金额
考点:窗口函数 + 分区 + order
—
14. 查询“未支付金额 > 已支付金额”的用户
sum(未支付) > sum(已支付),返回 user_id。
(思路关键:group by + 条件聚合)
—
15. 查询同一个用户上一笔订单距离下一笔订单相差多少天
典型的 LEAD / LAG 窗口函数题。
要求返回:
user_id | order_id | created_at | next_created_at | interval_days
🧨 🔥 第四部分:高难度(业务场景 + 常考)
16. 查询商品的“30 天滚动销售额”
对每个商品每天算一个 “过去 30 天窗口” 的销售额(滑动窗口)。
需要窗口函数:
range between interval 29 day preceding and current row
—
17. 查询“近 7 天连续无登录”的用户
login(user_id, login_at)
某用户 7 天内完全没有登录过 → 返回这些 user_id。
(涉及补全日期 + group by + max/min)
—
18. 找出被“重复提交”的订单(相同 user、相同金额、相同时间段)
判断风控类问题:短时间内几乎相同的订单。
(考点:分组、having、近时间窗口)
—
19. 查询门店每天的“新增用户数”
用户第一单发生在该店,即视为该店新增。
(关键:min(created_at))
—
20. 查询“最近 10 分钟内下单次数 > 5 次”的用户(防刷)
典型反作弊滑窗题,有时需自连接或窗口函数实现。