Rails Postgres Error GROUP BY子句或用于聚合函数

时间:2014-02-15 18:31:23

标签: ruby-on-rails postgresql

在SQLite(开发)中我没有任何错误,但在Postgres的生产中我收到以下错误。我真的不明白这个错误。

PG::Error: ERROR:  column "commits.updated_at" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: ...mmits"."user_id" = 1 GROUP BY mission_id ORDER BY updated_at...
                                                             ^
: SELECT COUNT(*) AS count_all, mission_id AS mission_id FROM "commits"  WHERE "commits"."user_id" = 1 GROUP BY mission_id ORDER BY updated_at DESC

我的控制器方法:

  def show
    @user = User.find(params[:id])
    @commits = @user.commits.order("updated_at DESC").page(params[:page]).per(25)
    @missions_commits = @commits.group("mission_id").count.length
  end

更新

所以我深入研究了这个PostgreSQL特有的烦恼,我很惊讶Ruby on Rails指南中没有提到这个异常。

我正在使用psql (PostgreSQL) 9.1.11

因此,根据我的理解,我需要指定在使用GROUP_BY子句时应该使用哪个列。我认为使用SELECT会有所帮助,如果您需要SELECT很多列,这可能很烦人。

Interesting discussion here

无论如何,当我查看错误时,每次光标都指向updated_at。在SQL查询中,rails始终为ORDER BY updated_at。所以我尝试了这个可怕的问题:

@commits.group("mission_id, date(updated_at)")
        .select("date(updated_at), count(mission_id)")
        .having("count(mission_id) > 0")
        .order("count(mission_id)").length

它给了我以下SQL

SELECT  date(updated_at), count(mission_id) 
FROM "commits"  
WHERE "commits"."user_id" = 1 
GROUP BY mission_id, date(updated_at) 
HAVING count(mission_id) > 0 
ORDER BY updated_at DESC, count(mission_id) 
LIMIT 25 OFFSET 0

错误是一样的。

注意,无论ORDER BY updated_at是什么,即使我想按其他方式订购。

此外,我不希望仅通过mission_id对updated_at进行分组。

这个PostgreSQL错误只是误导而且解决它的解释很少。我已经尝试了stackoverflow侧边栏中的许多公式,没有任何作用,总是出现相同的错误。

更新2: 所以我让它工作,但由于自动updated_at,它需要对ORDER BY updated_at进行分组。我如何仅按mission_id计算?

@missions_commits = @commits.group("mission_id, updated_at").count("mission_id").size 

2 个答案:

答案 0 :(得分:1)

请在此处查看PostgreSQL GROUP BY的文档:

http://www.postgresql.org/docs/9.3/interactive/sql-select.html#SQL-GROUPBY

基本上,与Sqlite(和MySQL)不同,postgres要求选择或订购的任何列必须出现在聚合函数或group by子句中。

如果你仔细想想,你会发现这实际上是有道理的。 Sqlite / MySQL在引擎盖下作弊并默默地丢弃这些字段(不确定技术上会发生什么)。

或者如果你按照字段进行分组,可以考虑另一种方式,订购它的重点是什么?除非你在有序字段上也有一个聚合函数,这怎么会有意义呢?

答案 1 :(得分:1)

我是客人,你想要显示与提交有关的不同任务的一般数量,无论如何它不会是页面上的数字。

试试这个:

@commits = @user.commits.order("updated_at DESC").page(params[:page]).per(25)
@missions_commits = @user.commits.distinct.count(:mission_id)

但是,如果您想在页面上获取不同任务的数量,我认为它应该是:

@missions_commits = @commits.collect(&:mission_id).uniq.count

<强>更新

在Rails 3中,distinct不存在,但应以这种方式使用纯SQL计数:

@missions_commits = @user.commits.count(:mission_id, distinct: true)