跳到主要内容

腾讯大数据面试SQL-朋友圈点赞数Top N

⚠️ 待修正

一、题目背景

这道题来自腾讯微信事业群的数据分析岗面试。朋友圈是微信的核心社交功能,每天产生数十亿条内容和百亿级点赞。运营和产品团队需要快速识别"爆款朋友圈"——哪些用户的内容最能引发互动,哪些话题最受欢迎。

业务场景:朋友圈信息流的排序算法需要参考"内容质量分",点赞数Top N就是最直接的信号。产品经理也会关注"每个用户的Top朋友圈"来评估用户的社交影响力。这道SQL就是内容质量打分的基础查询。

二、题目

现有朋友圈表 t8_moments 和点赞表 t8_likes,请查询每个用户的朋友圈中,点赞数排名前2的朋友圈内容及点赞数。

朋友圈表 t8_moments:

+------------+----------+------------------------+---------------------+
| moment_id | user_id | content | post_time |
+------------+----------+------------------------+---------------------+
| 101 | 1 | 今天天气真好! | 2023-03-01 10:00:00 |
| 102 | 1 | 分享一首好听的歌 | 2023-03-01 12:00:00 |
| 103 | 2 | 周末去哪儿玩呢? | 2023-03-01 14:00:00 |
| 104 | 2 | 推荐一家很棒的餐厅 | 2023-03-02 09:00:00 |
| 105 | 3 | 打卡新开的咖啡店 | 2023-03-02 10:00:00 |
| 106 | 1 | 晚上加班中... | 2023-03-02 20:00:00 |
| 107 | 3 | 今天的日落真美 | 2023-03-03 18:00:00 |
+------------+----------+------------------------+---------------------+

点赞表 t8_likes:

+------------+---------------+---------------------+
| moment_id | like_user_id | like_time |
+------------+---------------+---------------------+
| 101 | 2 | 2023-03-01 10:05:00 |
| 101 | 3 | 2023-03-01 10:10:00 |
| 101 | 4 | 2023-03-01 10:15:00 |
| 101 | 5 | 2023-03-01 11:00:00 |
| 102 | 2 | 2023-03-01 12:30:00 |
| 102 | 3 | 2023-03-01 13:00:00 |
| 103 | 1 | 2023-03-01 14:30:00 |
| 103 | 3 | 2023-03-01 15:00:00 |
| 103 | 4 | 2023-03-01 16:00:00 |
| 104 | 1 | 2023-03-02 09:30:00 |
| 105 | 1 | 2023-03-02 10:30:00 |
| 105 | 2 | 2023-03-02 11:00:00 |
| 106 | 2 | 2023-03-02 20:30:00 |
| 107 | 1 | 2023-03-03 18:30:00 |
| 107 | 2 | 2023-03-03 19:00:00 |
| 107 | 4 | 2023-03-03 19:30:00 |
+------------+---------------+---------------------+

三、思路分析

本题需要查询每个用户朋友圈中点赞数排名前2的内容,核心步骤如下:

  1. 先统计每条朋友圈的点赞数;
  2. 关联朋友圈表获取朋友圈内容和所属用户;
  3. 使用 ROW_NUMBER() 按用户分组、按点赞数降序排名;
  4. 筛选排名前2的记录;
维度评分
题目难度⭐️⭐️⭐️
题目清晰度⭐️⭐️⭐️⭐️⭐️
业务常见度⭐️⭐️⭐️⭐️⭐️

四、逐步推导

1. 统计每条朋友圈的点赞数

执行SQL

select moment_id,
count(distinct like_user_id) as like_cnt
from t8_likes
group by moment_id

执行结果

+------------+----------+
| moment_id | like_cnt |
+------------+----------+
| 101 | 4 |
| 102 | 2 |
| 103 | 3 |
| 104 | 1 |
| 105 | 2 |
| 106 | 1 |
| 107 | 3 |
+------------+----------+

2. 关联朋友圈表获取内容和所属用户,按用户分组对点赞数排名

执行SQL

select m.user_id,
m.moment_id,
m.content,
t.like_cnt,
row_number() over (partition by m.user_id order by t.like_cnt desc) as rn
from t8_moments m
left join (
select moment_id,
count(distinct like_user_id) as like_cnt
from t8_likes
group by moment_id
) t on m.moment_id = t.moment_id

执行结果

+----------+------------+------------------------+----------+-----+
| user_id | moment_id | content | like_cnt | rn |
+----------+------------+------------------------+----------+-----+
| 1 | 101 | 今天天气真好! | 4 | 1 |
| 1 | 102 | 分享一首好听的歌 | 2 | 2 |
| 1 | 106 | 晚上加班中... | 1 | 3 |
| 2 | 103 | 周末去哪儿玩呢? | 3 | 1 |
| 2 | 104 | 推荐一家很棒的餐厅 | 1 | 2 |
| 3 | 107 | 今天的日落真美 | 3 | 1 |
| 3 | 105 | 打卡新开的咖啡店 | 2 | 2 |
+----------+------------+------------------------+----------+-----+

3. 筛选每个用户排名前2的朋友圈

执行SQL

select user_id,
moment_id,
content,
like_cnt,
rn as rank_num
from (
select m.user_id,
m.moment_id,
m.content,
t.like_cnt,
row_number() over (partition by m.user_id order by t.like_cnt desc) as rn
from t8_moments m
left join (
select moment_id,
count(distinct like_user_id) as like_cnt
from t8_likes
group by moment_id
) t on m.moment_id = t.moment_id
) tmp
where rn <= 2
order by user_id, rn

执行结果

+----------+------------+------------------------+----------+----------+
| user_id | moment_id | content | like_cnt | rank_num |
+----------+------------+------------------------+----------+----------+
| 1 | 101 | 今天天气真好! | 4 | 1 |
| 1 | 102 | 分享一首好听的歌 | 2 | 2 |
| 2 | 103 | 周末去哪儿玩呢? | 3 | 1 |
| 2 | 104 | 推荐一家很棒的餐厅 | 1 | 2 |
| 3 | 107 | 今天的日落真美 | 3 | 1 |
| 3 | 105 | 打卡新开的咖啡店 | 2 | 2 |
+----------+------------+------------------------+----------+----------+

五、常见坑点

坑1:LEFT JOIN vs INNER JOIN 对无点赞朋友圈的影响

如果某条朋友圈还没有人点赞,用 INNER JOIN 会让它直接消失。应该用 LEFT JOIN 保留所有朋友圈,点赞数用 COALESCE(like_cnt, 0) 填充为0。虽然排名可能靠后,但数据完整性不能丢。

坑2:COUNT DISTINCT 的必要性

同一个用户可以多次点赞同一条朋友圈(取消再点),如果不加 DISTINCT 会重复计算。COUNT(DISTINCT like_user_id) 确保每个用户只算一次。

坑3:ROW_NUMBER vs RANK 选哪个

如果两条朋友圈点赞数相同,ROW_NUMBER() 会随机选一条排前面,RANK()DENSE_RANK() 会并列。产品需求是"取前2条",用 ROW_NUMBER 更合适——点赞数相同时取任意2条即可。

六、举一反三

  1. 按时间窗口统计:WHERE 条件限制 post_time 范围,实现"本周最火朋友圈Top N"
  2. 点赞+评论综合分:关联评论表,加权计算 total_score = like_cnt * 0.4 + comment_cnt * 0.6
  3. 好友维度的点赞排名:限定点赞用户必须是被统计用户的好友(关联好友关系表),只看"熟人圈"的热度
  4. 点赞速度分析:计算每条朋友圈达成Top 2点赞数所花的时间,识别"秒赞"异常行为

七、知识点总结

考点说明
LEFT JOIN + COUNT DISTINCT保留无点赞的朋友圈,去重统计真实点赞数
ROW_NUMBER() OVER(PARTITION BY)按用户分组、按点赞数降序排名
WHERE rn <= N外层筛选每组前N条记录
子查询分层先聚合点赞数→关联朋友圈→排名→筛选,逐层处理

八、建表语句和数据插入

点击展开 DDL & DML
CREATE TABLE t8_moments (
moment_id bigint COMMENT '朋友圈ID',
user_id bigint COMMENT '用户ID',
content string COMMENT '朋友圈内容',
post_time string COMMENT '发布时间'
) COMMENT '朋友圈表';

-- 建表语句:点赞表
CREATE TABLE t8_likes (
moment_id bigint COMMENT '朋友圈ID',
like_user_id bigint COMMENT '点赞用户ID',
like_time string COMMENT '点赞时间'
) COMMENT '点赞表';

-- 数据插入:朋友圈表
INSERT INTO t8_moments VALUES
(101, 1, '今天天气真好!', '2023-03-01 10:00:00'),
(102, 1, '分享一首好听的歌', '2023-03-01 12:00:00'),
(103, 2, '周末去哪儿玩呢?', '2023-03-01 14:00:00'),
(104, 2, '推荐一家很棒的餐厅', '2023-03-02 09:00:00'),
(105, 3, '打卡新开的咖啡店', '2023-03-02 10:00:00'),
(106, 1, '晚上加班中...', '2023-03-02 20:00:00'),
(107, 3, '今天的日落真美', '2023-03-03 18:00:00');

-- 数据插入:点赞表
INSERT INTO t8_likes VALUES
(101, 2, '2023-03-01 10:05:00'),
(101, 3, '2023-03-01 10:10:00'),
(101, 4, '2023-03-01 10:15:00'),
(101, 5, '2023-03-01 11:00:00'),
(102, 2, '2023-03-01 12:30:00'),
(102, 3, '2023-03-01 13:00:00'),
(103, 1, '2023-03-01 14:30:00'),
(103, 3, '2023-03-01 15:00:00'),
(103, 4, '2023-03-01 16:00:00'),
(104, 1, '2023-03-02 09:30:00'),
(105, 1, '2023-03-02 10:30:00'),
(105, 2, '2023-03-02 11:00:00'),
(106, 2, '2023-03-02 20:30:00'),
(107, 1, '2023-03-03 18:30:00'),
(107, 2, '2023-03-03 19:00:00'),
(107, 4, '2023-03-03 19:30:00');
📱关注公众号

「数据仓库技术」文章同步更新,不错过每一篇干货

微信公众号二维码
💬加群交流

备注「数据仓库技术」加入社群,每日一道大厂SQL真题

交流微信二维码

你可能还想看