跳到主要内容

SQL 搜索关键词热度排名及趋势:GROUP BY + ORDER BY(小红书面试题)

一、题目

统计各关键词在 5 月和 6 月的搜索用户数(去重),计算 6 月较 5 月的环比变化率,按 6 月搜索量降序输出 Top10。

假设有搜索日志表 t7_search_log

+----------+----------+-------------------+
| user_id | keyword | search_time |
+----------+----------+-------------------+
| u01 | 连衣裙 | 2025-05-15 10:00 |
| u02 | 连衣裙 | 2025-05-18 14:00 |
| u01 | 连衣裙 | 2025-06-02 09:00 |
| u03 | 连衣裙 | 2025-06-05 11:00 |
| u04 | 连衣裙 | 2025-06-10 16:00 |
| u01 | 防晒霜 | 2025-05-20 08:00 |
| u02 | 防晒霜 | 2025-06-01 10:00 |
| u03 | 防晒霜 | 2025-06-03 12:00 |
| u04 | 防晒霜 | 2025-06-08 15:00 |
| u05 | 防晒霜 | 2025-06-12 09:00 |
| u02 | 露营 | 2025-06-05 08:00 |
| u03 | 露营 | 2025-06-10 14:00 |
| u04 | 露营 | 2025-06-15 17:00 |
+----------+----------+-------------------+

二、思路分析

  1. 使用 substr(search_time, 1, 7) 提取年月维度;
  2. 按关键词分组,用 CASE WHEN 条件聚合分别统计5月和6月的去重搜索人数;
  3. 计算环比变化率 = (6月 - 5月) / 5月,按6月搜索量降序取Top10。
维度评分
题目难度⭐️⭐️
题目清晰度⭐️⭐️⭐️⭐️⭐️
业务常见度⭐️⭐️⭐️⭐️

三、逐步推导

1.分别统计每个关键词在5月和6月的搜索量

执行SQL

select keyword,
count(distinct case when substr(search_time, 1, 7) = '2025-05' then user_id end) as may_cnt,
count(distinct case when substr(search_time, 1, 7) = '2025-06' then user_id end) as jun_cnt
from t7_search_log
group by keyword

查询结果

+----------+----------+----------+
| keyword | may_cnt | jun_cnt |
+----------+----------+----------+
| 防晒霜 | 1 | 4 |
| 连衣裙 | 2 | 3 |
| 露营 | 0 | 3 |
+----------+----------+----------+
3 rows selected (0.691 seconds)(https://www.dwsql.com)

2.计算环比变化并取Top10

执行SQL

select keyword,
may_cnt,
jun_cnt,
case when may_cnt > 0 then round((jun_cnt - may_cnt) / may_cnt, 4) else null end as mom_change
from (
select keyword,
count(distinct case when substr(search_time, 1, 7) = '2025-05' then user_id end) as may_cnt,
count(distinct case when substr(search_time, 1, 7) = '2025-06' then user_id end) as jun_cnt
from t7_search_log
group by keyword
) t
order by jun_cnt desc
limit 10

查询结果

+----------+----------+----------+-------------+
| keyword | may_cnt | jun_cnt | mom_change |
+----------+----------+----------+-------------+
| 防晒霜 | 1 | 4 | 3.0 |
| 连衣裙 | 2 | 3 | 0.5 |
| 露营 | 0 | 3 | NULL |
+----------+----------+----------+-------------+
3 rows selected (0.481 seconds)(https://www.dwsql.com)

四、常见坑点

坑1:环比计算中除零处理 — 上月搜索量可能为0(如"露营"的may_cnt=0),直接除法 (jun_cnt - may_cnt) / may_cnt 会触发除零错误。使用 case when may_cnt > 0 then ... else null end 安全处理,上月无数据时环比不可计算,返回NULL。

坑2:COUNT DISTINCT vs COUNT(*) — 同一用户在同月内可能多次搜索同一关键词(如u01在5月和6月都搜索过"连衣裙"),使用 count(distinct user_id) 统计去重搜索人数,反映真实用户覆盖;若用 count(*) 会重复计数,高估搜索热度。

坑3:时间范围需精确到月substr(search_time, 1, 7) 提取年月前缀(格式"YYYY-MM"),确保只统计目标月份的数据。注意前提是 search_time 为统一格式的字符串,若为 timestamp 类型需改用 date_format(search_time, 'yyyy-MM')

五、知识点总结

考点说明
CASE WHEN 条件聚合结合 substr 提取年月,在单个聚合查询中按条件分别统计各月搜索量,避免多次子查询或自连接
COUNT DISTINCT 去重同一用户同月多次搜索同一关键词应去重,count(distinct user_id) 反映真实搜索人数而非搜索次数
GROUP BY + ORDER BY + LIMIT分组聚合后按目标列降序排序取Top N,是排行榜类需求的通用写法
环比计算与除零保护case when 判断分母 > 0 再计算除法,防止上月数据为0导致的除零异常,无数据时返回NULL

六、建表语句

点击展开 DDL & DML
-- 建表语句
create table t7_search_log (
user_id string comment '用户id',
keyword string comment '搜索关键词',
search_time string comment '搜索时间'
) comment '搜索日志表';

-- 插入数据
insert into t7_search_log(user_id, keyword, search_time) values
('u01','连衣裙','2025-05-15 10:00'),
('u02','连衣裙','2025-05-18 14:00'),
('u01','连衣裙','2025-06-02 09:00'),
('u03','连衣裙','2025-06-05 11:00'),
('u04','连衣裙','2025-06-10 16:00'),
('u01','防晒霜','2025-05-20 08:00'),
('u02','防晒霜','2025-06-01 10:00'),
('u03','防晒霜','2025-06-03 12:00'),
('u04','防晒霜','2025-06-08 15:00'),
('u05','防晒霜','2025-06-12 09:00'),
('u02','露营','2025-06-05 08:00'),
('u03','露营','2025-06-10 14:00'),
('u04','露营','2025-06-15 17:00');
📱关注公众号

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

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

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

交流微信二维码

你可能还想看