我正在尝试创建一份留下评论的独特患者列表。代码字很好,直到我上传到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" = $1 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:没有这样的函数:substring:SELECT &#34;评论&#34;。* FROM&#34;评论&#34;在哪里&#34;评论&#34;。&#34; clinician_id&#34; =?订购 BY substring(created_at,1.8)desc
我意识到这是一个常见问题,我对SQL缺乏经验,因此我无法获取代码,因此它可以在我的开发和生产环境中工作。我在SO上阅读的答案并没有使用Ruby来获取SQL并超越我的经验水平。
答案 0 :(得分:8)
你不能将SELECT *
与GROUP BY some_column
结合在Postgres中(除非some_column
是PK),因为这是一个矛盾。所有非聚合列(在聚合函数之外的SELECT
,HAVING
或ORDER BY
子句中使用)必须位于GROUP BY
列表中 - 主键列可以替换表的所有列。否则,未定义从聚合集中选择哪个值。
当存在
GROUP BY
或存在任何聚合函数时,它 对于引用未分组的SELECT
列表表达式无效 除聚合函数内或未分组列时的列 功能上依赖于分组列,因为它会 否则为一个未分组的人返回一个以上的可能值 柱。如果分组列(或a),则存在功能依赖性 其子集)是包含该表的表的主键 未分组的专栏。
已知某个其他RDBMS在这里玩肮脏的技巧并允许这个并选择任意值......
您似乎想要一个已评论的唯一患者列表,每个最新评论。 Postgres中最简单的方法是使用DISTINCT ON
:
SELECT DISTINCT ON (patient_id) *
FROM comments
WHERE clinician_id = $1
ORDER BY patient_id, created_at DESC NULLS LAST;
但是这不会与SQLite一起飞行 - 它不应该在循环中开始:
仅当NULLS LAST
可以为NULL时, created_at
才有意义:
DISTINCT ON
的详细信息: