0

グループに多くのユーザーが含まれるUserとの2 つのモデルがあります。Group1 つのクエリを使用して各グループのユーザー数をカウントする場合は、次の SQL を使用できます。

select id, (select count(1) from users where group_id = groups.id) from groups

これを ActiveRecord で効率的に行うことは可能ですか?

明確にするために、このクエリはすべてのグループ ID と各グループのユーザー数を一覧表示します。

4

3 に答える 3

1

いずれかを使用してカウントを取得できます

  1. 関連付けの使用

    group = Group.find(1) #find group with id = 1
    group.users.count    # count users whose group_id = 1 calls db everytime
     or  
    group.users.size  # get size from cache if group.users loaded
    
  2. または直接

    User.where(:group_id=>1).count
    

count ヘルパーは、指定された条件でデータベースに対して count(*) クエリを起動します http://apidock.com/rails/ActiveRecord/Calculations/countでその他のオプションを確認してください

また、レールガイドを確認することをお勧めします

于 2012-08-03T21:35:47.873 に答える
0

結合を使用して効率的な解決策を見つけました:

Group.all(
  :select => "groups.id, count(u.group_id) as users_count",
  :joins  => "LEFT OUTER JOIN users u ON u.group_id = groups.id",
  :group  => "groups.id"
)
于 2012-08-05T03:26:55.420 に答える
0

最初の解決策は、クエリを ActiveRecord に変換し、サブクエリを使用することです。

subquery = User.where("users.group_id = groups.id").select('count(1)')
groups_with_count = Group.select(:id, "(#{subquery.to_sql}) as users_count")

または、同じ結果を得るためにSQLグループ化を使用します

groups_with_count = Group.joins(:users).select(:id, 'count(users.id) as users_count').group(:id)

どちらの場合も、MINIMAL raw sql を使用した 1 つのクエリで結果を取得できます。

groups_with_count.each { |group| puts "#{group.id} => #{group.users_count}" }

追記事項

subquery = User.via(:group).select('count(1)')次のヘルパーを使用して、よりシンプルで保守しやすい最初のサブクエリを作成できます。

より適切なサブクエリを作成するために、いくつかのプロジェクトでこのコードを使用しました。

class ApplicationRecord < ActiveRecord::Base
    # transform Raw sql that references an association such as: Shift.where('shifts.id = checkins.shift_id')
    # into a simpler version Shift.via(:checkin) if shift have the checkin relationship
    # No support for polymorphic association
    # Basic support for "through" reflection (using join)
    def via(name)
        association = reflect_on_association(name)

        raise ArgumentError, "#{name} is not a valid association of #{self.class.name}" unless association
        raise NotImplementedError if association.polymorphic?

        join_keys = association.join_keys
        table_column = arel_table[join_keys.foreign_key]
        association_column = Arel::Table.new(association.table_name)[join_keys.key]

        if association.through_reflection?
            through_association = association.through_reflection
            table_column = Arel::Table.new(through_association.table_name)[join_keys.foreign_key]

            joins(through_association.name).where(table_column.eq(association_column))
        else
            where(table_column.eq(association_column))
        end
    end
end
于 2019-10-17T12:21:36.857 に答える