跳到主要内容

SQL 搜索日志热门TopN查询词:GROUP BY + ORDER BY + LIMIT(百度面试题)

一、题目

现有一张搜索日志表 t5_search_log,记录了用户每次搜索的查询词。请统计搜索次数最多的前10个查询词(Top 10热门搜索词)。

搜索日志表 t5_search_log:

+----------+-------------+----------------------+
| user_id | query_word | search_time |
+----------+-------------+----------------------+
| u01 | 天气预报 | 2023-03-01 08:00:00 |
| u02 | 股票行情 | 2023-03-01 08:05:00 |
| u01 | 百度地图 | 2023-03-01 09:00:00 |
| u03 | 天气预报 | 2023-03-01 09:10:00 |
| u04 | 世界杯 | 2023-03-01 09:15:00 |
| u02 | 天气预报 | 2023-03-01 09:20:00 |
| u05 | 高考成绩 | 2023-03-01 10:00:00 |
| u01 | 股票行情 | 2023-03-01 10:30:00 |
| u03 | 百度地图 | 2023-03-01 11:00:00 |
| u04 | 天气预报 | 2023-03-01 11:30:00 |
| u06 | 深度学习 | 2023-03-01 12:00:00 |
| u07 | 天气预报 | 2023-03-01 12:30:00 |
| u08 | ChatGPT | 2023-03-01 13:00:00 |
| u05 | 世界杯 | 2023-03-01 14:00:00 |
| u06 | 百度地图 | 2023-03-01 15:00:00 |
+----------+-------------+----------------------+

二、思路分析

本题是最基础的聚合排序题,考察 GROUP BY + ORDER BY + LIMIT:

  1. 分组统计GROUP BY query_word 按查询词分组,COUNT(1) 统计搜索次数
  2. 降序排列ORDER BY search_cnt DESC 按搜索次数从高到低
  3. 取前N条LIMIT 10 取出排名前10的热门词
维度评分
题目难度⭐️
题目清晰度⭐️⭐️⭐️⭐️⭐️
业务常见度⭐️⭐️⭐️⭐️⭐️

三、逐步推导

统计热门搜索词Top 10

一道查询即可完成:按查询词分组→统计次数→降序→取前10。

执行SQL

select query_word,
count(1) as search_cnt
from t5_search_log
group by query_word
order by search_cnt desc
limit 10

执行结果

+-------------+-------------+
| query_word | search_cnt |
+-------------+-------------+
| 天气预报 | 5 |
| 百度地图 | 3 |
| 股票行情 | 2 |
| 世界杯 | 2 |
| 高考成绩 | 1 |
| ChatGPT | 1 |
| 深度学习 | 1 |
+-------------+-------------+
7 rows selected (8.319 seconds)(https://www.dwsql.com)

四、常见坑点

坑1:COUNT vs COUNT DISTINCT 的选择

如果同一个用户多次搜索同一个词(如 u01 搜了两次"天气预报"),用 COUNT(1) 算的是搜索次数,用 COUNT(DISTINCT user_id) 算的是搜索人数。本题目的是"热门搜索词"应该算次数,所以用 COUNT(1)。

坑2:数据倾斜导致部分Reducer过载

搜索日志中热门词(如"天气预报")的搜索量可能是长尾词的数万倍。GROUP BY query_word 时,热门词所在的Reducer处理的数据量远大于其他Reducer,形成数据倾斜——绝大多数任务已完成,只有1-2个Reducer在"卡住"。

Spark SQL 的应对方案:

  • 开启AQE自适应优化spark.sql.adaptive.enabled = true,Spark 3.0+ 的AQE会自动检测倾斜分区并拆分为多个子任务并行处理
  • 两阶段聚合(加盐法):先给热点key加随机后缀(如 concat(query_word, '_', floor(rand()*10)))做局部预聚合,再去掉后缀做最终聚合。两次GROUP BY虽然多了一次Shuffle,但避免了单点瓶颈
  • 调整shuffle分区数:增大 spark.sql.shuffle.partitions(默认200),让每个Reducer处理更少的数据

面试中主动讨论数据倾斜,展示工程经验会显著加分。

坑3:LIMIT 的方言差异

LIMIT 10 在 Hive/Spark/MySQL 通用。SQL Server 用 SELECT TOP 10,Oracle 用 WHERE ROWNUM <= 10。面试时注明你用的SQL方言即可。

五、知识点总结

考点说明
GROUP BY + COUNT按查询词聚合,统计每个词的搜索频率
ORDER BY DESC降序排列,热度最高的排最前面
LIMIT N取前N条记录,实现Top N效果

六、建表语句和数据插入

点击展开 DDL & DML
create table t5_search_log (
user_id string COMMENT '用户ID',
query_word string COMMENT '查询词',
search_time string COMMENT '搜索时间'
) COMMENT '搜索日志表';

insert into t5_search_log values
('u01', '天气预报', '2023-03-01 08:00:00'),
('u02', '股票行情', '2023-03-01 08:05:00'),
('u01', '百度地图', '2023-03-01 09:00:00'),
('u03', '天气预报', '2023-03-01 09:10:00'),
('u04', '世界杯', '2023-03-01 09:15:00'),
('u02', '天气预报', '2023-03-01 09:20:00'),
('u05', '高考成绩', '2023-03-01 10:00:00'),
('u01', '股票行情', '2023-03-01 10:30:00'),
('u03', '百度地图', '2023-03-01 11:00:00'),
('u04', '天气预报', '2023-03-01 11:30:00'),
('u06', '深度学习', '2023-03-01 12:00:00'),
('u07', '天气预报', '2023-03-01 12:30:00'),
('u08', 'ChatGPT', '2023-03-01 13:00:00'),
('u05', '世界杯', '2023-03-01 14:00:00'),
('u06', '百度地图', '2023-03-01 15:00:00');
📱关注公众号

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

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

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

交流微信二维码

你可能还想看