You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails Active Record #or查询结构兼容报错及解决方法咨询

解决ActiveRecord #or查询结构不兼容问题

原代码报错原因:#or要求参与合并的两个查询必须结构完全兼容,包括关联表(joins)、选中字段(select)、排序条件(order)等。你第一个查询关联了program: :future_end_date_sessions,第二个关联了path: :future_end_date_sessions,两者的joins结构不一致,因此触发ArgumentError。

方案一:使用EXISTS子查询(推荐)

通过子查询分别判断Product关联的Program/Path是否存在符合条件的session,既避免结构不一致问题,也具备更优的查询性能:

原生SQL写法

Product.where(
  <<~SQL
    EXISTS (
      SELECT 1 FROM programs
      JOIN sessions ON sessions.program_id = programs.id
      WHERE programs.id = products.learning_item_id
        AND products.learning_item_type = 'Program'
        AND sessions.future_end_date = TRUE -- 替换为future_end_date_sessions的实际筛选逻辑
    )
    OR
    EXISTS (
      SELECT 1 FROM paths
      JOIN sessions ON sessions.path_id = paths.id
      WHERE paths.id = products.learning_item_id
        AND products.learning_item_type = 'Path'
        AND sessions.future_end_date = TRUE -- 替换为future_end_date_sessions的实际筛选逻辑
    )
  SQL
)

ActiveRecord Arel写法(更贴合Rails风格)

Product.where(
  # 匹配关联有效Program的Product
  Product.arel_table[:learning_item_type].eq('Program').and(
    Program.where(id: Product.arel_table[:learning_item_id])
           .joins(:future_end_date_sessions)
           .arel.exists
  ).or(
    # 匹配关联有效Path的Product
    Product.arel_table[:learning_item_type].eq('Path').and(
      Path.where(id: Product.arel_table[:learning_item_id])
          .joins(:future_end_date_sessions)
          .arel.exists
    )
  )
)

方案二:LEFT JOIN + WHERE筛选

通过左连接同时关联Program和Path的session,再筛选出至少一边有匹配记录的Product,最后用distinct避免重复结果:

Product.left_joins(program: :future_end_date_sessions, path: :future_end_date_sessions)
       .where("programs.id IS NOT NULL OR paths.id IS NOT NULL")
       .distinct

内容的提问来源于stack exchange,提问作者David Geismar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 15:25:21