分组错误: 错误: 列必须出现在GROUP BY子句中或用于聚合函数

40

我在我的控制器中有代码,它根据最高平均评分对专辑进行排名(使用了来自此解决方案的代码如何通过has_many评论关系显示最高评级的专辑):

@albums = Album.joins(:reviews).select("*, avg(reviews.rating) as average_rating").group("albums.id").order("average_rating DESC")

这段代码在我的开发环境(sqlite3)下完美运行,但是当我将代码推到Heroku和PostgreSQL时,出现了这个错误:

PG::GroupingError: ERROR:  column "reviews.id" must appear in the GROUP BY clause or be used in an aggregate function

我意识到这是一个相当常见的问题,由于我对SQL经验不足,在重构代码时遇到了一些困难,以便在我的开发和生产环境中都能正常运行。

2个回答

38
您不允许在没有将其添加到GROUP BY子句或应用聚合函数(例如avg())的情况下选择reviews.id(隐式通过通配符*选择)。解决方案是执行以下操作之一:
  1. 从您的选择中删除通配符*
  2. 将字段reviews.id添加到您的group子句中
  3. 显式选择reviews.id并对其应用聚合函数(例如sum(reviews.id))
  4. 使用表特定的通配符albums.*替换通配符*
基于您的评论,第二和第三个选项在您的情况下没有多大意义。我已添加了第四个选项。

1
明白了,所以我应该像这样在选择子句中明确列出每个列名,而不是使用通配符 * 吗?@albums = Album.joins(:reviews).select("reviews.rating, albums.id, albums.name, albums.artist, albums.picture, avg(reviews.rating) as average_rating").group("albums.id").order("average_rating DESC") - Reuben
1
你可以尝试使用 @albums = Album.joins(:reviews).select("albums.*, avg(reviews.rating) as average_rating").group("albums.id").order("average_rating DESC") - slash
我不太确定您实际想要选择哪些字段。但是在您的评论中,您试图选择 reviews.ratingavg(reviews.rating)。因此,在一个结果行中,您正在尝试同时获取当前行的评分和平均评分?您可以编辑您的问题并添加两个表 reviews 和 albums 的结构,以及您期望接收哪些字段。 - slash
你之前的评论解决了问题。对于“@albums”,我正在尝试按照专辑的评分高低顺序获取我的Album模型中的所有字段,以在视图中显示。我的最后一条评论是我努力理解你的第一个建议(从选择中删除通配符)的不足之处。 - Reuben

3

我想分享一个使用Active Record(Sinatra)编写的Ruby代码。

我需要在“order by”函数中添加“group by”,所以代码行如下:

原始代码:

@models = Port.all.order('number asc')

to:

@models = Port.select(:id, :device_id, :number, :value, :sensor, :UOM).all.order('number asc').group(:id,:sensor,:UOM)

它完美地运行了,只要记得在这种情况下将ID字段 "Port.id" 添加到组子句中,否则就会引发此错误,并且如@slash所提到的,你无法使用特殊函数(通过通配符*隐式选择或在我的情况下使用"all")来实现这一点。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接