0

我有一个简单的has_many:通过排列,如下图

# 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

我有一份员工名单。对于该列表,我想获取包含该列表中至少一名员工的每个组。我将如何以一种不是非常低效的方式完成此任务?我对 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)

所以发生的事情是,首先使用左外连接(将表中的列与表中的列匹配)连接表groups,然后再次使用左外连接(将表中的列与表中的列匹配)桌子)。group_assignmentsgroup_idgroup_assignmentsidgroupsemployeesemployee_idgroup_assignmentsidemployees

然后,我们选择'employees'.'id'员工列表中员工数组中(员工的 id)所在的所有行,我们通过使用:映射employees_list到他们的 id 来获得这些行。这里是简写:。mapemployees_list.map(&:id)map(&:id)map { |e| e.id }

请注意,您可以使用joins而不是includes此处,但如果一名员工是多个组的成员,您将得到重复。有点微妙但有用的东西要知道。

希望这是有道理的!

于 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 回答