如何通过单条查询从SectionAdvice与Lecture表获取Activity数据?
可以通过单条查询实现需求
你可以直接从Activity模型出发,通过EXISTS子查询结合OR条件一次性筛选出符合要求的记录,同时避免重复数据。
步骤1:补充Activity模型的反向关联(可选但推荐)
先给Activity添加与SectionAdvice、Lecture的反向关联,让查询更符合Rails规范:
class Activity < ApplicationRecord belongs_to :area has_many :section_advices has_many :lectures end
步骤2:单条查询实现方案
方式1:使用SQL字符串(直观易读)
# 假设contract_ids是你要传入的合同ID数组,participant_id是目标参与者ID Activity.kept .where( "EXISTS (SELECT 1 FROM section_advices WHERE section_advices.activity_id = activities.id AND section_advices.contract_id IN (?) AND section_advices.kept = ?) OR EXISTS (SELECT 1 FROM lectures WHERE lectures.activity_id = activities.id AND lectures.participant_id = ? AND lectures.kept = ?)", contract_ids, true, participant_id, true ) .distinct
方式2:使用Arel(更安全,避免SQL注入风险)
如果不想直接写SQL字符串,可以用Rails的Arel构造查询:
section_advice_condition = SectionAdvice.kept .where(contract_id: contract_ids) .where(SectionAdvice.arel_table[:activity_id].eq(Activity.arel_table[:id])) .exists lecture_condition = Lecture.kept .where(participant_id: participant_id) .where(Lecture.arel_table[:activity_id].eq(Activity.arel_table[:id])) .exists Activity.kept.where(section_advice_condition.or(lecture_condition)).distinct
方案说明
- EXISTS子查询:分别检查Activity是否关联符合条件的SectionAdvice或Lecture,比JOIN更高效(不会产生重复行)。
- OR条件:满足任意一个关联条件的Activity都会被选中。
- distinct:确保最终结果中没有重复的Activity记录(比如某个Activity同时关联符合条件的SectionAdvice和Lecture时)。
- kept:所有关联表的查询都加上了这个scope,确保只查询未被软删除的记录。
对比原方案的优势
原方案是两次查询后在Ruby层面合并数据,不仅会产生额外的数据库请求,还可能出现重复数据需要手动去重;单条查询直接在数据库层面完成筛选和去重,性能更优,代码也更简洁。
内容的提问来源于stack exchange,提问作者snloD
相关产品推荐
相关产品推荐

