GroupingError: ERROR: 列 " " 必须出现在 GROUP BY 子句中或在聚合函数中使用

7 浏览
0 Comments

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,超出了我的经验水平。

0
0 Comments

在Postgres中,不能将SELECT *GROUP BY some_column结合使用,因为这是一个矛盾的操作(除非它从单个表中选择,并且some_column是其主键)。所有非聚合的列(在聚合函数之外的SELECTHAVINGORDER 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)

0