You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL中GROUP BY p是否不合理?如何改写获取产品平均评分的查询?

你的SQL查询问题解析

首先说结论:你的查询在不同数据库里表现不一样,大概率会报错,GROUP BY p这种写法不通用也不规范。

为什么GROUP BY p有问题?

  • 多数主流数据库(比如PostgreSQL、开启了ONLY_FULL_GROUP_BY的MySQL)不支持直接按整个表别名分组。SQL标准要求,SELECT里出现的非聚合字段(也就是p.*里的每一列),必须都出现在GROUP BY子句里,或者被聚合函数包裹。你写GROUP BY p相当于没明确指定分组的字段,数据库不知道怎么处理。
  • 就算某些数据库允许这种写法,也可能出现逻辑错误——比如如果product表存在重复行(虽然主键不会重复,但万一其他字段有重复场景),分组结果可能不符合预期。

要返回全部产品详情,正确的分组方式是什么?

有两种靠谱的写法:

  1. 明确列出所有product字段
    把p.*里的每一列都写到GROUP BY里,比如:

    SELECT
      p.id, p.name, p.price, p.description, -- 列出product表所有字段
      AVG(r.rating) AS avg_rating
    FROM product p
    LEFT JOIN reviews r ON r.productId = p.id
    GROUP BY p.id, p.name, p.price, p.description -- 和SELECT里的非聚合字段一一对应
    

    这种写法符合所有数据库的SQL标准,绝对不会出错,就是字段多的时候写起来麻烦。

  2. 按主键分组(推荐)
    如果product表有主键(比如id),那在MySQL 8.0+、PostgreSQL 10+这些新版本数据库里,只需要按主键分组就行。因为主键唯一标识一条产品记录,数据库会自动关联其他字段,不需要全部列出来:

    SELECT
      p.*,
      AVG(r.rating) AS avg_rating
    FROM product p
    LEFT JOIN reviews r ON r.productId = p.id
    GROUP BY p.id
    

    这种写法简洁又规范,是最优解。

额外优化建议

没有评论的产品,avg_rating会返回NULL,如果想让它显示0更友好,可以用COALESCE函数处理:

SELECT
  p.*,
  COALESCE(AVG(r.rating), 0) AS avg_rating
FROM product p
LEFT JOIN reviews r ON r.productId = p.id
GROUP BY p.id

内容的提问来源于stack exchange,提问作者managerit017

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 09:13:30