【问题标题】:Complex join in RailsRails 中的复杂连接
【发布时间】:2016-04-12 20:38:55
【问题描述】:

我有两个模型:ProgramStudent 和 StudentCheckIn(一个学生可以有很多班级签到,所以 StudentCheckIn 属于 ProgramStudent)。 ProgramStudent 有一个 date_of_rank 日期列,指示他们何时达到当前排名。

我想生成一个查询,以标识自 date_of_rank 以来签到次数超过 X 的所有 ProgramStudents。

StudentCheckIn 模型具有以下范围:

scope :since, -> (date) { where("checked_in_at >= ?", date) }

我可以构造一个合并此范围的查询,如下所示:

ProgramStudent.joins(:student_check_ins)
    .merge(StudentCheckIn.since(Date.today - 2.months))
    .group("program_students.id")
    .having("count(*) > ?", 15)

生成以下 SQL:

SELECT "program_students".* FROM "program_students" 
INNER JOIN "student_check_ins" 
ON "student_check_ins"."program_student_id" = "program_students"."id" 
WHERE (checked_in_at >= '2016-02-12') 
GROUP BY program_students.id 
HAVING count(*) > 15

这将返回自固定日期(在本例中为两个月前)以来签到超过 15 次的所有 ProgramStudents,但我希望查询使用单个 ProgramStudent 的 date_of_rank,而不是固定日期。有没有办法用 ActiveRecord 做到这一点?如果没有,如何使用原始 SQL 来完成?

【问题讨论】:

    标签: sql ruby-on-rails postgresql ruby-on-rails-4 rails-activerecord


    【解决方案1】:

    这是您的目标 SQL:

    SELECT "program_students".* FROM "program_students" 
    INNER JOIN "student_check_ins" 
    ON "student_check_ins"."program_student_id" = "program_students"."id" 
    WHERE (checked_in_at >= "program_students"."date_of_rank") 
    GROUP BY program_students.id, program_students.date_of_rank 
    HAVING count(*) > 15
    

    我怀疑您的 since 范围可以采用列名,因为任何字符串输入都可能会被转义,但您可以将 where 子句放在最后的 ARel 中:

    ProgramStudent.joins(:student_check_ins).
      where("student_check_ins.checked_in_at >= program_students.date_of_rank").
      group("program_students.id, program_students.date_of_rank").
      having("count(*) > ?", 15)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-08
      • 2015-07-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多