Active Record OR查询:两列匹配不同列表时空列表返回空结果问题
问题原因
你遇到的问题本质是SQL中IN子句的空列表处理逻辑:当IN后的参数列表为空时,会生成IN ()这类非法SQL语法,ActiveRecord为了避免报错,会自动将包含空列表的IN/NOT IN条件替换为恒假表达式(比如1=0),因此只要任意一个列表为空,整个查询条件就会恒假,返回空结果。
另外你原来的写法将两个条件耦合在同一段SQL字符串中,无法单独判断某个条件是否需要生效,进一步放大了这个问题。
解决方案
将两个条件拆分,用动态判断的方式拼接查询,空列表对应的条件直接不加入查询逻辑即可,推荐优先用ActiveRecord原生的hash条件写法,不需要手写SQL字符串,更安全也更易维护:
情况1:你需要筛选「最高成就者ID在指定列表、且教室ID在指定列表」的班级
# 两个入参列表,允许为空 achiever_ids = [1,2,3,4] room_ids = [1,2,3,4] # 初始化查询对象 query = school.classes # 列表不为空时才加对应条件 query = query.where(highest_achiever_id: achiever_ids) if achiever_ids.present? query = query.where(room_id: room_ids) if room_ids.present? # 执行查询拿到结果 target_classes = query
情况2:你需要筛选「最高成就者ID不在指定列表、且教室ID不在指定列表」的班级
只需要把where改成where.not即可:
achiever_ids = [1,2,3,4] room_ids = [1,2,3,4] query = school.classes query = query.where.not(highest_achiever_id: achiever_ids) if achiever_ids.present? query = query.where.not(room_id: room_ids) if room_ids.present? target_classes = query
如果你的业务逻辑要求某个列表为空时,对应条件不生效、筛选所有匹配内容,以上写法完全可以满足需求,不会再出现空列表返回空结果的问题。
内容的提问来源于stack exchange,提问作者aDev
相关产品推荐
相关产品推荐

