Reputation: 909
In SQLite (development) I don't have any errors, but in production with Postgres I get the following error. I don't really understand the error.
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
My controller method:
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
UPDATE:
So i digged further into this PostgreSQL specific annoyance and I am surprised that this exception is not mentioned in the Ruby on Rails Guide.
I am using psql (PostgreSQL) 9.1.11
So from what I understand, I need to specify which column that should be used whenever you use the GROUP_BY
clause. I thought using SELECT
would help, which can be annoying if you need to SELECT
a lot of columns.
Anyways, when I look at the error, everytime the cursor is pointed to updated_at
. In the SQL query, rails will always ORDER BY updated_at
. So I have tried this horrible query:
@commits.group("mission_id, date(updated_at)")
.select("date(updated_at), count(mission_id)")
.having("count(mission_id) > 0")
.order("count(mission_id)").length
which gives me the following 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
the error is the same.
Note that no matter what it will ORDER BY updated_at, even if I wanted to order by something else.
Also I don't want to group the records by updated_at just by mission_id.
This PostgreSQL error is just misleading and has little explanation to solving it. I have tried many formulas from the stackoverflow sidebar, nothing works and always the same error.
UPDATE 2:
So I got it to work, but it needs to group the updated_at
because of the automatic ORDER BY updated_at
. How do I count only by mission_id
?
@missions_commits = @commits.group("mission_id, updated_at").count("mission_id").size
Upvotes: 0
Views: 2131
Reputation: 17145
I guest you want to show general number of distinct Missions related with Commits, anyway it won't be number on page.
Try this:
@commits = @user.commits.order("updated_at DESC").page(params[:page]).per(25)
@missions_commits = @user.commits.distinct.count(:mission_id)
However if you want to get the number of distinct Missions on page I suppose it should be:
@missions_commits = @commits.collect(&:mission_id).uniq.count
Update
In Rails 3, distinct
did not exist, but pure SQL counting should be used this way:
@missions_commits = @user.commits.count(:mission_id, distinct: true)
Upvotes: 1
Reputation: 19879
See the docs for PostgreSQL GROUP BY here:
http://www.postgresql.org/docs/9.3/interactive/sql-select.html#SQL-GROUPBY
Basically, unlike Sqlite (and MySQL) postgres requires that any columns selected or ordered on must appear in an aggregate function or the group by clause.
If you think it through, you'll see that this actually makes sense. Sqlite/MySQL cheat under the hood and silently drop those fields (not sure that's technically what happens).
Or thinking about it another way if you are grouping by a field, what's the point of ordering it? How would that even make sense unless you also had an aggregate function on the ordered field?
Upvotes: 1