Skip to content

.group and .having of little usefulness with PostgreSQL #1515

Closed
@jaroslawr

Description

@jaroslawr

When using MySQL, .group and .having can be used to accomplish the very common task of finding records from SQL table table_a by specifying some conditions on some tables joining table_a, i.e. table_b, table_c etc. So, if I want to find all the users that have paid more then four times, I can do:

User.joins(:payments).group('users.id').having('count(payments.id) > 4')

This however doesn't work with PostgreSQL, which will in this case throw an error message similar to this one:

ActiveRecord::StatementInvalid: PGError: ERROR: column "users.email" must 
appear in the GROUP BY clause or be used in an aggregate function

This is because in PostgreSQL the columns that appear in the FROM clause have to be the same ones that appear in the GROUP by clause. Correct me if I'm wrong, but from what I see you can fix it only by using .select('users.id,users.email,..."), but in this case you either have to manually list all the columns or you get crippled objects returned with only some attributes present. This forces PostgreSQL users to either come up with some ugly workarounds or to use find_by_sql for any but the simplest queries concerning only one table. I don't know what's the most "Railsy" way of fixing it, but I think it would at least be helpful to have a method that would return all the column names qualified by the table name, like this:

module ActiveRecord
  class Base
    def all_columns
      column_names.collect { |c| "#{table_name}.#{c}" }.join(",")
    end
  end
end

That would make .group and .having usable in PostgreSQL like this:

User.joins(:payments).group(User.all_columns).having('count(payments.id) > 4')

In the end I think it would be great if Rails provided some shorthand notation for doing the same thing, like this:

User.joins(:payments).group(:users).having('count(payments.id) > 4')

Edit:

Maybe .group with no arguments could do just that?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions