查找至少有一个成员属于列表的组列表(rails,SQL)

时间:2013-01-10 07:57:07

标签: sql ruby-on-rails sqlite postgresql

我有一个简单的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。

3 个答案:

答案 0 :(得分: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_assignments列与{匹配id表中的{1}}列,然后groups再次使用左外连接(employees表中的employee_idgroup_assignments匹配id表中的列。

然后我们选择所有行employees(员工的ID)在员工列表中的员工数组中,我们通过将'employees'.'id'映射到他们的ID来获得employees_listmap。这里的employees_list.map(&:id)是:map(&:id)的缩写。

请注意,您可以在此处使用map { |e| e.id }而不是joins,但如果一名员工是多个组的成员,那么您将获得重复项。要知道一些微妙但有用的东西。

希望有意义!

答案 1 :(得分:0)

这是一般的想法,但根据您的数据,您可能需要选择不同的。

Group.includes(:group_assignments => :employee).where(:employee => {:id => ?}, @employees.map(&:id))

答案 2 :(得分:0)

Group.joins(:group_assignments).where("group_assignments.employee_id in (?)", @employees.map(&:id))