select
avg(distinct score) avg_score
from
user_action_tb a
join recommend_tb b on a.user_id = b.rec_user
where
a.hobby_l = b.rec_info_l
当然可以!你问的是:
牛客网 SQL47:推荐内容准确的用户平均评分
我们来完整、清晰地讲解这道题的 题目解析 + 解题思路 + 易错点 + 优化建议,让你真正“知其然也知其所以然”。
🧩 题目名称(官方描述):
推荐内容准确的用户平均评分
🔗 原题链接:
✅ 一、题目要求
从两张表中查询数据:
表结构说明
1. user_action_tb(用户行为表)
user_id | 用户 ID |
hobby_l | 用户的兴趣标签(一级分类) |
score | 用户对内容的评分(数值) |
2. recommend_tb(推荐记录表)
rec_user | 被推荐的用户 ID |
rec_info_l | 推荐的内容标签(一级分类) |
🎯 查询目标:
计算 当推荐内容与用户兴趣匹配时,这些用户的平均评分。
即:
- 当
recommend_tb.rec_user = user_action_tb.user_id - 且
recommend_tb.rec_info_l = user_action_tb.hobby_l
👉 这些记录被认为是“推荐准确”的,我们要对它们的 score 求平均值。
✅ 二、示例数据 + 输出分析
输入数据
user_action_tb
1 | 美食 | 4 |
1 | 旅游 | 4 |
2 | 旅游 | 5 |
3 | 影视 | 3 |
recommend_tb
1 | 旅游 |
2 | 旅游 |
3 | 音乐 |
匹配过程分析
我们找满足两个条件的记录:
1 | 美食 → ❌ 旅游? | 否 | ❌ | |
1 | 旅游 → ✔️ 旅游? | 是 | ✔️ → 参与(score=4) | |
2 | 旅游 → ✔️ 旅游? | 是 | ✔️ → 参与(score=5) | |
3 | 影视 → ❌ 音乐? | 否 | ❌ |
✅ 只有两条记录匹配:
- user_id=1, hobby_l='旅游' → score=4
- user_id=2, hobby_l='旅游' → score=5
👉 平均评分 = (4 + 5) / 2 = 4.5
✅ 三、正确 SQL 写法
SELECT
AVG(score) AS avg_score
FROM
user_action_tb a
JOIN recommend_tb b
ON a.user_id = b.rec_user
AND a.hobby_l = b.rec_info_l;
✅ 四、关键解题思路拆解
步骤 1:确定连接方式
- 两表通过
user_id = rec_user关联 - 必须使用 INNER JOIN(或等价的 JOIN)
- 因为我们只关心“匹配成功”的情况
步骤 2:添加业务判断条件
- 不仅要用户相同,还要兴趣标签 == 推荐标签
- 所以把
a.hobby_l = b.rec_info_l放在ON条件中
⚠️ 注意:不能写成:
JOIN recommend_tb b ON a.user_id = b.rec_user WHERE a.hobby_l = b.rec_info_l
虽然结果一样,但逻辑上更推荐把所有关联条件放在 ON 中,保持语义清晰。
步骤 3:聚合函数选择
- 使用
AVG(score)直接求平均 - ❌ 不要用
AVG(DISTINCT score)比如两个人都打 4 分,会被当成一个 → 结果错误!
📌 示例:如果两个匹配记录都是 score=4,应该返回 4.0,而不是去重后还是 4 —— 数学上没问题,但样本量错了。
步骤 4:别名注意
- 输出字段必须是
avg_score(题目要求别名一致) - 否则判题系统会报 “答案错误”
✅ 五、常见错误写法对比
| 会引入不匹配的 NULL 记录,干扰结果 |
| 错误去重,导致统计偏差 |
单独放 | 在 LEFT JOIN 下出错,但在 INNER JOIN 中可接受 |
子查询嵌套 | 多此一举,此题无需复杂结构 |
✅ 六、进阶思考(面试加分项)
Q1:如果同一个用户多次被准确推荐,要不要去重?
- 题意没有说“按用户去重”
- 示例输出也没有去重 ➡️ 所以 不要去重用户,每条行为都算一次
Q2:如何改为“每个用户的推荐命中率”?
SELECT
a.user_id,
COUNT(CASE WHEN a.hobby_l = b.rec_info_l THEN 1 END) * 1.0 / COUNT(*) AS hit_rate
FROM user_action_tb a
LEFT JOIN recommend_tb b ON a.user_id = b.rec_user
GROUP BY a.user_id;
✅ 总结:解题四步法
1️⃣ 理清业务逻辑 | “推荐准确” = 用户ID相同 && 兴趣标签相同 |
2️⃣ 正确连表 | 使用 JOIN + 双条件 ON |
3️⃣ 聚合计算 |
,不加 DISTINCT |
4️⃣ 输出格式 | 别名必须为
|
✅ 最终答案(AC代码)
SELECT
AVG(score) AS avg_score
FROM
user_action_tb a
JOIN recommend_tb b
ON a.user_id = b.rec_user
AND a.hobby_l = b.rec_info_l;



京公网安备 11010502036488号