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

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

我正在尝试创建一个已发表评论的唯一患者列表。代码字很好,直到我上传到 heroku,它在 postgresql 中不起作用。

这是我的 Ruby .erb 代码来创建列表:

<% @comments.group(:patient_id).each_with_index do |comment, index| %>
    <div class="profile-post color-one">
       <span class="profile-post-numb"><%= index+1 %></span>
        <div class="profile-post-in">
            <h3 class="heading-xs"><a><%= link_to "#{comment.patient.first_name} #{comment.patient.last_name}", comment_path(comment) %></a></h3>
            <p>Lastest comment from <%= time_ago_in_words(comment.created_at) %> ago<i class="pull-right"><%= link_to "Edit", edit_comment_path(comment) %> <%= link_to "Delete", comment_path(comment), method: :delete, data: {confirm: 'Are you sure you want to delete'} %></i></p>
        </div>
    </div>
<% 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" =  GROUP BY patient_id  ORDER BY created_at desc

我已经尝试了其他SO问题的解决方案,例如20942477。其中说我应该将字段 comments.id 添加到我的组子句中:

<% @comments.group(:patient_id, :"comments.id").each_with_index do |comment, index| %>

这消除了 heroku 上的错误,但违背了组命令的目的 - 它不再仅显示唯一患者,而是列出所有患者。

我也尝试了 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 结合使用,因为这是矛盾的(除非它从单个 table 中选择并且 some_column 是它的主键)。所有非聚合列(在聚合函数外的 SELECTHAVINGORDER BY 子句中使用)必须在 GROUP BY 列表中 - 其中主键列(s ) 覆盖 table 的所有列。否则将从聚合集中选择哪个值是不确定的。

The manual:

When GROUP BY is present, or any aggregate functions are present, it is not valid for the SELECT list expressions to refer to ungrouped columns except within aggregate functions or when the ungrouped column is functionally dependent on the grouped columns, since there would otherwise be more than one possible value to return for an ungrouped column. A functional dependency exists if the grouped columns (or a subset thereof) are the primary key of the table containing the ungrouped column.

已知某个其他 RDBMS 在这里玩肮脏的把戏并允许这样做并选择任意值...

您似乎想要一份已发表评论的独特患者列表,每个患者都有 最新 条评论。 Postgres 中最简单的方法是 DISTINCT ON:

SELECT DISTINCT ON (patient_id) *
FROM   comments
WHERE  clinician_id = 
ORDER  BY patient_id, created_at DESC NULLS LAST;

但这不会与 SQLite 一起运行 - 它不应该在循环中开始。参见:

  • Generic Ruby solution for SQLite3 "LIKE" or PostgreSQL "ILIKE"?

NULLS LAST 仅当 created_at 可以为 NULL 时才相关:

  • Sort by column ASC, but NULL values first?

DISTINCT ON 的详细信息:

  • Select first row in each GROUP BY group?