GroupingError: ERROR: 列 " " 必须出现在 GROUP BY 子句中或在聚合函数中使用
GroupingError: ERROR: 列 " " 必须出现在 GROUP BY 子句中或在聚合函数中使用
我正在尝试创建一个唯一患者的评论列表。这段代码在上传到Heroku时工作正常,但在PostgreSQL中无法正常工作。
这是我用Ruby的.erb代码创建列表的方式:
<% @comments.group(:patient_id).each_with_index do |comment, index| %> <%= index+1 %><%= link_to "#{comment.patient.first_name} #{comment.patient.last_name}", comment_path(comment) %>
最新评论于 <%= time_ago_in_words(comment.created_at) %> 前<%= link_to "编辑", edit_comment_path(comment) %> <%= link_to "删除", comment_path(comment), method: :delete, data: {confirm: '确定要删除吗'} %> <% end %>
在控制器中,@comments被定义为:
def index @comments = current_clinician.comments.order("created_at desc") end
Heroku日志显示以下错误信息:
PG::GroupingError: ERROR: column "comments.id" must appear in the GROUP BY clause or be used in an aggregate function LINE 1: SELECT "comments".* FROM "comments" WHERE comments"."clini... ^ SELECT "comments".* *FROM "comments" WHERE "comments"."clinician_id" = $1 GROUP BY patient_id ORDER BY created_at desc
我尝试了其他一些SO(StackOverflow)问题中的解决方案,例如20942477。它说我应该将comments.id字段添加到我的group子句中:
<% @comments.group(:patient_id, :"comments.id").each_with_index do |comment, index| %>
这样可以消除Heroku上的错误,但它违背了group命令的目的 - 它不再只显示唯一的患者,而是列出了所有患者。
我还尝试了1780893中的解决方案。它说我应该更改ORDER BY:
@comments = current_clinician.comments.order("substring(created_at,1.8) desc")
这在本地产生了以下错误:
SQLite3::SQLException: no such function: substring: SELECT
"comments".* FROM "comments" WHERE "comments"."clinician_id" = ? ORDER
BY substring(created_at,1.8) desc
我意识到这是一个常见的问题,由于对SQL的经验不足,我很难在开发和生产环境中使代码正常工作。我在SO上读到的答案没有使用Ruby来获取SQL,超出了我的经验水平。
在Postgres中,不能将SELECT *
与GROUP BY some_column
结合使用,因为这是一个矛盾的操作(除非它从单个表中选择,并且some_column
是其主键)。所有非聚合的列(在聚合函数之外的SELECT
、HAVING
或ORDER BY
子句中使用的列)都必须在GROUP BY
列表中,其中主键列覆盖表的所有列。否则,将无法确定从聚合集中选择哪个值。
你似乎想要一个列出已评论的唯一患者,并且每个患者只显示最新的评论。在Postgres中,最简单的方法是使用DISTINCT ON
:
SELECT DISTINCT ON (patient_id) * FROM comments WHERE clinician_id = $1 ORDER BY patient_id, created_at DESC NULLS LAST;
但是这种方法在SQLite中不适用,实际上SQLite不应该参与其中。具体请参考以下链接:
- [Generic Ruby solution for SQLite3 "LIKE" or PostgreSQL "ILIKE"?](https://stackoverflow.com/questions/11249059/11278943#11278943)
如果created_at
可以为NULL,则NULLS LAST
是相关的:
- [Sort by column ASC, but NULL values first?](https://stackoverflow.com/questions/9510509/9511492#9511492)
关于DISTINCT ON
的详细信息,请参考以下链接:
- [Select first row in each GROUP BY group?](https://stackoverflow.com/questions/3800551/7630564#7630564)
感谢Erwin,那是一个非常有帮助的答案。我已经切换到在本地使用PostgreSQL,DISTINCT ON
给出了一个唯一患者的列表:.order("patient_id, created_at DESC").select('ON (patient_id) *').uniq.each_with_index do |comment, index|
现在患者的顺序是根据seed.rb
文件中创建顺序排序的。你有什么建议可以按照他们最新评论的created_at
进行排序吗?
- 将这个查询包装到一个具有不同ORDER BY
的外部查询中。以下是详细的说明:[stackoverflow.com/questions/24619117/...](http://stackoverflow.com/questions/24619117/24623210#24623210)