【问题标题】:Rails: Collect records whose join tables appear in two queriesRails:收集连接表出现在两个查询中的记录
【发布时间】:2019-06-14 05:41:40
【问题描述】:

这里有三个重要的模型:Objective、Student 和 Seminar。所有都与 has_and_belongs_to_many 相关联。

有一个 ObjectiveStudent 连接模型,其中包括“ready”和“points_all_time”列。有一个包含“优先级”列的 ObjectiveSeminar 连接模型。

我需要收集与给定学生以及给定研讨会相关的所有目标。

他们还需要在研讨会上标有高于零的“优先级”。所以我想我需要这条线:

obj_sems = ObjectiveSeminar.where(:seminar => given_seminar).where("priority > ?", 0)

最后,他们还需要是学生准备好的目标,但得分未超过 7。所以我认为我需要这条线:

obj_studs = ObjectiveStudent.where(:user => given_student, :ready => true).where("points_all_time <= ?", 7)

有没有办法收集连接表记录出现在上述两个查询中的所有目标?请注意,这两个列表都没有返回目标;他们分别返回objective_seminars和objective_students。我的最终目标是收集满足上述所有条件的目标。

或者我处理这一切都错了?

额外问题:我也很想按目标在给定研讨会中的优先级排序。但我担心这会给数据库负载增加太多。您对此有何看法?

提前感谢您的任何见解。

【问题讨论】:

    标签: ruby-on-rails jointable


    【解决方案1】:

    为了获得Objectives,您需要从那里开始查询。 为了使用AND 条件查询关联的表,您需要与这些表进行内部连接。 最后,您将需要一个 distinct 运算符来仅获取每个目标一次。

    (我认为)您需要的扩展版本是:

    Objective.joins(objective_seminars: :seminar, objective_student: :student).
      where(seminars: seminar_search_params, strudents: student_search_params).
      where('objective_seminars.priority > 0').
      where('objective_students.ready = 1 AND points_all_time <= 7').
      order('objective_seminars.priority ASC').
      distinct
    

    现在对于数据库负载,这一切都取决于您的索引和表的大小。 上述查询将转换为以下 SQL(或类似内容)。

    SELECT DISTINCT objectives.* FROM objectives
      INNER JOIN objective_students ON objective_students.objective_id = objectives.id
      INNER JOIN students ON students.id = objective_students.student_id
      INNER JOIN objective_seminars ON objective_seminars.objective_id = objectives.id
      INNER JOIN seminars ON seminars.id = objective_seminars.seminar_id
      WHERE seminars_query AND
        students_query AND
        objective_seminars.priority > 0 AND
        objective_students.ready = 1 AND points_all_time <= 7 AND
        objective_seminars.priority ASC
    

    因此,您需要添加或扩展索引,以便所有 5 个表查询都可以有一个索引来提供帮助。实际的索引实现取决于您,取决于您的应用程序的具体情况(读写负载、表大小、基数等)

    【讨论】:

    • 这帮助我到达了我需要的地方。起初,我收到一个错误,即目标没有“研讨会”列。但是我能够通过在所有行中使用引号语法来解决这个问题:where("objective_seminars.seminar_id == ?",seminar.id)。谢谢。
    猜你喜欢
    • 2016-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 2020-03-25
    • 2016-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多