简体   繁体   English

Rails查找具有多个关联记录的记录

[英]Rails find record with multiple associated records

Say I have a Teacher model that has_many students through class_listings consisting of teacher_id and student_id: 假设我有一个Teacher模型,该模型通过class_listings包含了很多学生,包括Teacher_id和Student_id:

class Teacher < ActiveRecord::Base
  has_many :class_listings
  has_many :students, through: :class_listings
end

class ClassListing < ActiveRecord::Base
  belongs_to :teacher
  belongs_to :student
end

class Student < ActiveRecord::Base
  has_many :class_listings
  has_many :teachers, through: :class_listings
end

and there exists: 并且存在:

  • Teacher 1 having Student 1 老师1有学生1
  • Teacher 2 having Student 2 老师2有学生2
  • Teacher 3 having Student 1 and Student 2 老师3有学生1和学生2

How would I query for a teacher having student 1 and student 2? 我如何查询有学生1和学生2的老师?

I've tried 我试过了

Teacher.joins(:class_listings).where(class_listings: {student_id: [1,2]})

but that returns teachers with students 1 or 2 (ie teacher 1, 2, and 3) as opposed to teachers with students 1 and 2 (ie teacher 3). 但这会返回拥有学生1或2的老师(即老师1、2和3),而不是拥有学生1 2的老师(即老师3)。

Assuming that your class listings are uniq, you may also do it like that: 假设您的课程清单是唯一的,您也可以这样:

student_ids = [1, 2]
Teacher.where(
  id: Rel.select(:teacher_id).group(:teacher_id).where(student_id: student_ids)
    .having("count(student_id) = ?", student_ids.count)
)

SQL is: SQL是:

SELECT "teachers".* FROM "teachers" WHERE "teachers"."id" IN (
  SELECT "rels"."teacher_id" FROM "rels" WHERE "rels"."student_id" IN (1, 2)
  GROUP BY "rels"."teacher_id" HAVING count(student_id) = 2
)

PS: I use Rel model instead of ClassListing , sorry PS:我使用Rel模型而不是ClassListing ,抱歉
PPS: I like @histocrat's solution too. PPS:我也喜欢@histocrat的解决方案。

This is awkward. 好尴尬 Here's one way without writing straight SQL: 这是不编写直接SQL的一种方法:

Teacher.where(id: ClassListing.where(student_id: 1).select(:teacher_id))
       .where(id: ClassListing.where(student_id: 2).select(:teacher_id))

This is composed of multiple where clauses, but it will only actually make one SQL query, something like Select * from teachers where id in (Select teacher_id from ClassListing where student_id = 1) AND id in (Select teacher_id from ClassListing where student_id = 2) . 它由多个where子句组成,但实际上只会进行一个SQL查询,例如Select * from teachers where id in (Select teacher_id from ClassListing where student_id = 1) AND id in (Select teacher_id from ClassListing where student_id = 2)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM