我有一个简单的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。
答案 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)
所以发生的事情是groups
和group_assignments
表首先与左外连接相连接(将group_id
表中的group_assignments
列与{匹配id
表中的{1}}列,然后groups
再次使用左外连接(employees
表中的employee_id
与group_assignments
匹配id
表中的列。
然后我们选择所有行employees
(员工的ID)在员工列表中的员工数组中,我们通过将'employees'.'id'
映射到他们的ID来获得employees_list
:map
。这里的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))