SQL技术问询:如何实现分组记录数超2条时计算平均值及筛选至少有两条评分的物品求平均
1. 基础SQL问题解答
咱们先解决这个基础问题:要判断某列分组的记录数是否超过两条,满足条件才计算该组的平均值,核心思路是用GROUP BY分组后,靠HAVING子句来筛选符合要求的分组(毕竟WHERE没法用聚合函数筛选分组结果,HAVING专门干这个事儿)。
给你个通用的示例,假设你的表叫your_table,用来分组的列是group_col,要算平均值的列是value_col:
SELECT group_col, AVG(value_col) AS avg_value FROM your_table -- 如果需要排除空值的话可以加这行 WHERE value_col IS NOT NULL GROUP BY group_col -- 只留记录数超过2的分组 HAVING COUNT(*) > 2;
这里关键的两点:
COUNT(*)是统计每个分组的总记录数,用HAVING COUNT(*) > 2就能过滤出记录数超2的分组- 只有通过
HAVING筛选的分组,才会执行AVG()计算平均值
2. 业务场景SQL问题修正
再来说你的业务场景需求:针对每个至少有两条评分记录的物品,计算它的平均评分。先给你指出你写的SQL里的几个小问题:
- 你用
count(distinct rating) as rating,这统计的是不同评分值的个数,不是该物品的总评分记录数,和需求不符哦 - 分组后没选
item列,最后结果里没法知道每个平均值对应哪个物品 - 缺少
HAVING子句来筛选出有2条及以上评分记录的物品
给你修正后的SQL:
SELECT item, COUNT(*) AS total_rating_records, -- 这行可选,用来显示该物品的评分总条数 AVG(rating) AS average_rating FROM rates WHERE rating IS NOT NULL -- 排除空的评分记录 GROUP BY item HAVING COUNT(*) >= 2; -- 只保留有2条及以上评分的物品
要是你还需要关联item表,拿到物品的描述、分类这些信息,就用JOIN来关联:
SELECT i.id AS item_id, i.description AS item_description, COUNT(r.rating) AS total_rating_records, AVG(r.rating) AS average_rating FROM rates r JOIN item i ON r.item = i.id WHERE r.rating IS NOT NULL GROUP BY i.id, i.description -- 分组要包含所有非聚合的列哦 HAVING COUNT(r.rating) >= 2;
这样就完全符合你的需求啦,只会给有两条及以上评分记录的物品计算平均评分~
内容的提问来源于stack exchange,提问作者Nefton




