我有两个模型: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?
答案 0 :(得分:1)
这是您的目标:
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)