短视频平台常见SQL面试题
# 短视频平台常见 SQL 面试题,你学会了吗?
本文整理了短视频平台业务场景下的三道常见 SQL 面试题,涉及窗口函数、多表联结、时间计算等核心知识点。
# 数据表结构
某短视频公司数据库包含三张核心表:
# 表一:用户视频信息明细表
| 用户id | 视频id | 点赞数 | 发布日期 | 用户累计粉丝数 | 视频类别 |
|---|---|---|---|---|---|
| sz001 | 10001 | 71 | 2022/6/1 | 144 | 生活 |
| sz003 | 10005 | 69 | 2022/6/1 | 97 | 生活 |
| sz004 | 10007 | 65 | 2022/6/1 | 177 | 资讯 |
| sz002 | 10005 | 64 | 2022/6/1 | 95 | 生活 |
| sz005 | 10057 | 97 | 2022/6/1 | 197 | 资讯 |
| sz001 | 10051 | 95 | 2022/6/2 | 275 | 生活 |
| sz003 | 10006 | 98 | 2022/6/2 | 202 | 生活 |
| sz004 | 10008 | 70 | 2022/6/2 | 219 | 资讯 |
| sz002 | 10006 | 75 | 2022/6/2 | 285 | 生活 |
| sz005 | 10058 | 96 | 2022/6/2 | 264 | 资讯 |
| sz001 | 10052 | 81 | 2022/6/3 | 243 | 生活 |
| sz004 | 10056 | 56 | 2022/6/3 | 246 | 资讯 |
| sz005 | 10010 | 53 | 2022/6/3 | 265 | 资讯 |
字段说明:包含用户 id、发布视频 id、视频点赞数、视频发布日期、视频类别和用户的粉丝数。
# 表二:主播开播明细表
| 主播id | 直播间id | 开播时间 |
|---|---|---|
| sz001 | R001 | 2022/5/4 20:00 |
| sz003 | R004 | 2022/5/4 19:00 |
| sz002 | R005 | 2022/5/4 18:00 |
字段说明:包含主播 id、主播开直播房间的 id 号,和开播的时间。
# 表三:直播间用户信息明细表
| 观众id | 进入的直播间id | 进入时间 |
|---|---|---|
| g001 | R001 | 2022/5/4 20:00 |
| g002 | R001 | 2022/5/4 20:02 |
| g003 | R005 | 2022/5/4 18:04 |
| g004 | R001 | 2022/5/4 20:06 |
| g005 | R001 | 2022/5/4 20:33 |
字段说明:包含进入直播间观看的观众 id、进入的直播间 id 和观众进入的时间。
# 业务需求与解题思路
# 问题 1:找出每个用户点赞数最高的视频
需求细节:点赞数相同时按照视频 id 最大的记录。
# 思路拆解
- 查询字段:用户 id、视频 id、点赞数
- 分组排序:按用户 id 分组,再根据点赞数降序排序,若点赞数相同则按视频 id 降序
- 筛选记录:选择每个用户点赞数最高的视频(排名第 1 的)
关键技巧:使用窗口函数 row_number() 而非 group by,因为窗口函数不会减少原表行数,可以保留明细数据的同时进行组内排序。
# SQL 解法
首先,用窗口函数计算每个用户视频的排名:
select
用户id,
视频id,
点赞数,
row_number() over(
partition by 用户id
order by 点赞数 desc, 视频id desc
) as 排名
from 用户视频信息明细表;
**中间结果**:
| 用户id | 视频id | 点赞数 | 排名 |
| :----- | :----- | :----- | :--- |
| sz001 | 10051 | 95 | 1 |
| sz001 | 10052 | 81 | 2 |
| sz001 | 10001 | 71 | 3 |
| sz002 | 10006 | 75 | 1 |
| sz002 | 10005 | 64 | 2 |
| sz003 | 10006 | 98 | 1 |
| sz003 | 10005 | 69 | 2 |
| sz004 | 10008 | 70 | 1 |
| sz004 | 10007 | 65 | 2 |
| sz004 | 10056 | 56 | 3 |
| sz005 | 10057 | 97 | 1 |
| sz005 | 10058 | 96 | 2 |
| sz005 | 10010 | 53 | 3 |
然后,筛选排名为 1 的记录:
```sql
select 用户id, 视频id, 点赞数
from (
select
用户id,
视频id,
点赞数,
row_number() over(
partition by 用户id
order by 点赞数 desc, 视频id desc
) as 排名
from 用户视频信息明细表
) t
where 排名 = 1;
最终结果:
| 用户id | 视频id | 点赞数 |
|---|---|---|
| sz001 | 10051 | 95 |
| sz002 | 10006 | 75 |
| sz003 | 10006 | 98 |
| sz004 | 10008 | 70 |
| sz005 | 10057 | 97 |
# 问题 2:找出粉丝数在 6 月 2 号提升最多的 3 个用户
需求细节:对比 6 月 1 号的粉丝数,计算 6 月 2 号的涨粉量,取前 3 名。
# 思路拆解
- 计算涨粉数:6月2号粉丝数 - 6月1号粉丝数
- Top N 筛选:按涨粉数降序排列,取前 3 个用户
关键技巧:利用 if() 函数配合 sum() 进行条件聚合。当日期为 6/2 时取正数,为 6/1 时取负数,相加即得差值。
# SQL 解法
第一步,计算每个用户的涨粉数:
select
用户id,
sum(if(发布日期 = "2022/6/2", 用户累计粉丝数, -用户累计粉丝数)) as 涨粉数
from 用户视频信息明细表
where 发布日期 in ("2022/6/2", "2022/6/1")
group by 用户id;
中间结果:
| 用户id | 涨粉数 |
|---|---|
| sz001 | 131 |
| sz003 | 105 |
| sz004 | 42 |
| sz002 | 190 |
| sz005 | 67 |
第二步,取涨粉数前 3 名:
select 用户id, 涨粉数
from (
select
用户id,
sum(if(发布日期 = "2022/6/2", 用户累计粉丝数, -用户累计粉丝数)) as 涨粉数
from 用户视频信息明细表
where 发布日期 in ("2022/6/2", "2022/6/1")
group by 用户id
) t
order by 涨粉数 desc
limit 3;
最终结果:
| 用户id | 涨粉数 |
|---|---|
| sz002 | 190 |
| sz001 | 131 |
| sz003 | 105 |
# 问题 3:找出开播三分钟内无人进入的直播房间号
需求细节:找出那些主播开播后,3 分钟内没有观众进入的直播间。
# 思路拆解
- 多表联结:用
直播间id关联主播开播表和观众进入表(Left Join) - 时间判断:观众进入时间 > 开播时间 + 3分钟,或观众id为空(无人进入)
- 筛选逻辑:使用
date_add()函数计算开播后 3 分钟的时间节点
# 关键函数:date_add
- 作用:在日期中添加或减去指定的时间间隔
- 语法:
date_add(date, interval expr type) - 示例:
date_add(a.开播时间, interval +3 minute)表示开播时间后 3 分钟
# SQL 解法
先联结两表查看全量数据:
select
a.主播id,
a.直播间id,
b.观众id,
a.开播时间,
b.进入时间
from 主播开播明细表 a
left join 直播间用户信息明细表 b
on a.直播间id = b.进入的直播间id;
联结结果分析:
- R004(sz003):观众id 为 Null,表示无人进入
- R005(sz002):观众 g003 在 18:04 进入,但开播时间是 18:00,刚好是 4 分钟后,超过 3 分钟限制
筛选开播 3 分钟内无人进入的房间:
select
a.主播id,
a.直播间id,
b.观众id,
a.开播时间,
b.进入时间
from 主播开播明细表 a
left join 直播间用户信息明细表 b
on a.直播间id = b.进入的直播间id
and b.进入时间 > date_add(a.开播时间, interval +3 minute)
where b.观众id is null;
最终结果:
| 主播id | 直播间id | 观众id | 开播时间 | 进入时间 |
|---|---|---|---|---|
| sz003 | R004 | Null | 2022/5/4 19:00 | Null |
| sz002 | R005 | Null | 2022/5/4 18:00 | Null |
结果说明:
- R004:完全无人进入
- R005:有观众进入,但都在 3 分钟之后(被
>条件过滤,只剩 Null 记录)
# 本题考点总结
- 窗口函数
row_number():适用于"每个用户下每种类别的排序"类业务需求,可在保留明细的同时进行组内排序 - 条件聚合:使用
if()+sum()实现行转列计算,避免使用子查询自连接,性能更优 - 多表联结策略:
- 先通过
Left Join保留所有直播间信息 - 用时间条件在
on子句中过滤不符合时间要求的观众记录 - 最后通过
where筛选观众id为空的记录(即 3 分钟内无人进入)
- 先通过
- 时间函数:掌握
date_add()的用法,灵活处理时间区间判断问题
学习建议:遇到复杂的业务需求,建议采用多维度拆解法——将大问题拆分为多个简单的子问题(如先计算涨粉数,再取 Top N),逐步构建 SQL 逻辑。