我的数据库包括参加训练的跑步者
所以:
class Runner
has_many :attendances
has_many :attended_happenings, through: :attendances, source: :happening
end
class Attendance < ActiveRecord::Base
belongs_to :happening
belongs_to :runner
end
class Happening
has_many :attendances, dependent: :destroy
has_many :attendees, through: :attendances, source: :runner
end
我想找到所有在过去9周内没有参加任何活动的跑步者。在runner模型中,我创建了一个scope :inactive_for_nine_weeks
:
left_joins(:attendances)
.joins("join happenings on attendances.happening_id = happenings.id")
.where("attendances.id is null")
.where("happenings.started_at > ?", 9.weeks.ago)
我想我需要left_join
的出勤率,以获得跑步者,* 没有 * 有出勤率,然后我需要做一个定期加入的事件。
虽然我知道应该有结果,但我没有得到任何结果,所以显然执行得很差。
从作用域中获取计数而产生的SQL:
SELECT COUNT(*) FROM "runners" LEFT OUTER JOIN "attendances" ON "attendances"."runner_id" = "runners"."id" join happenings on attendances.happening_id = happenings.id WHERE (attendances.id is null) AND (happenings.started_at > '2023-02-27 08:54:12.460052')
任何提示将不胜感激!
2条答案
按热度按时间zhte4eai1#
ActiveRecord中最直接的解决方案是只做一个子查询:
Runner.inactive_since
给出以下SQL:您还可以使用EXISTS而不是WHERE IN作为一种轻微的优化(在某些DB上)。
如果你需要它,你可以去更优化的解决方案,不是像横向或交叉连接或使用Postgres上的
COUNT(happenings.*) FILTER (WHERE started_at < ?) = 0
多语言。但是我会从子查询开始,当你到达它的时候,我会跨过那座桥。shyt4zoc2#
这是针对您的问题的SQL解决方案。
你首先需要交叉加入所有跑步者的所有hapenings得到所有的组合。
在那之后,你用LEFT JOIN检查哪个跑步者在比赛现场,其余的必须为空
fiddle