0

以下に示すように、単純な has_many :through 配置があります。

# employee.rb
class Employee < ActiveRecord::Base
  has_many :group_assignments
  has_many :groups, through: :group_assignments
  # ...
end

# group.rb
class Group < ActiveRecord::Base
  has_many :group_assignments
  has_many :employees, through: :group_assignments
  # ...
end

# group_assignment.rb
class GroupAssignment < ActiveRecord::Base
  belongs_to :employee
  belongs_to :group
end

私は従業員のリストを持っています。そのリストでは、そのリストに含まれる従業員を少なくとも 1 人含むすべてのグループを取得したいと考えています。恐ろしく非効率的でない方法でこれを達成するにはどうすればよいでしょうか? 私は Rails に不慣れで、SQL に非常に慣れていないため、かなり途方に暮れています。開発では SQLite を使用し、本番環境では PostgreSQL を使用しています。

4

3 に答える 3

2

という名前の従業員のリストの場合employees_list、これは機能します。

 Group.includes(:employees).where('employees.id' => employees_list.map(&:id))

これはおおよそ次のような SQL です。

SELECT "groups"."id" AS t0_r0,
  "groups"."created_at" AS t0_r1, "groups"."updated_at" AS t0_r2,
  "employees"."id" AS t1_r0, "employees"."created_at" AS t1_r1, "employees"."updated_at" AS t1_r2
  FROM "groups"
  LEFT OUTER JOIN "group_assignments" ON "group_assignments"."group_id" = "groups"."id"  
  LEFT OUTER JOIN "employees" ON "employees"."id" = "group_assignments"."employee_id" 
  WHERE "employees"."id" IN (1, 3)

つまりgroupsgroup_assignmentsテーブルは最初に左外部結合 (テーブル内の列をテーブル内のgroup_id列に一致させる) で結合され、次に再び左外部結合 (テーブル内の列をテーブル内の列に一致させる) で結合されます。テーブル)。group_assignmentsidgroupsemployeesemployee_idgroup_assignmentsidemployees

その後'employees'.'id'、従業員リストの従業員の配列に (従業員の ID) が含まれるすべての行を選択employees_listmapますemployees_list.map(&:id)。here は次のmap(&:id)短縮形です: map { |e| e.id }.

joinsここの代わりに使用できますがincludes、1 人の従業員が複数のグループのメンバーである場合、重複が発生することに注意してください。微妙だけど知っておくと便利なこと。

それが理にかなっていることを願っています!

于 2013-01-10T08:18:41.177 に答える
0

これは一般的な考え方ですが、データによっては、distinct を選択する必要がある場合があります。

Group.includes(:group_assignments => :employee).where(:employee => {:id => ?}, @employees.map(&:id))
于 2013-01-10T08:14:02.487 に答える
0

試す

Group.joins(:group_assignments).where("group_assignments.employee_id in (?)", @employees.map(&:id))
于 2013-01-10T08:18:07.933 に答える