如何将此原始查询转换为Active记录查询接口或arel?
我想找到至少有一个variant_type
= 1的variant
并且没有variant_type
= 2的任何variant
的variant_type
。
所以我的查询如下:
Course.where("id IN ( SELECT course_id FROM course_variants WHERE variant_type = 1 ) AND id NOT IN ( SELECT course_id FROM course_variants WHERE variant_type = 2 )")
此外, course
有很多course_variants
。
我在where子句中使用原始查询,我想使用Active记录接口或Arel来改进它,任何解决方案都适用于此?
谢谢!
使用输入更新预期输出
输入
course: {id=1, course_variants: [{variant_type: 1}, {variant_type: 2}]} course: {id=2, course_variants: [{variant_type: 1}, {variant_type: 3}]} course: {id=3, course_variants: [{variant_type: 2}, {variant_type: 3}]}
产量
course: {id=2, course_variants: [{variant_type: 1}, {variant_type: 3}]}
您可以稍微调整一下您的模型关联:
class Course < ActiveRecord::Base has_many :type_1_variants, class_name: "CourseVariant", -> { where(variant_type: 1) } has_many :non_type_3_variants, class_name: "CourseVariant", -> { where.not(variant_type: 3) } end Course.joins(:type_1_variants, :non_type_3_variants).group(:course_id).having('COUNT(course_variants.id) > 0').having('COUNT(non_type_3_variants_courses.id) > 0')
您可能需要将“non_type_3_variants_courses”替换为ARel在进行连接时生成的正确别名(我没有Rails环境)
您应该使用连接方法连接两个表courses
和course_variants
然后在where方法中定义条件,如下所示:
Course.joins("INNER JOIN course_variants on courses.id = course_variants.course_id") .where("course_variants.variant_type" => 1)
试试这个:
Course.where(id: CourseVariant.where(variant_type: 1).pluck(:course_id)).where.not(id: CourseVariant.where(variant_type: 2).pluck(:course_id))
希望这有帮助。 🙂
嘿,你可以尝试这种方式,它是优化的方式来找到这样的记录,这里不需要两次火灾:
您可以在Rails pluck中执行此操作以进行第二次查询:
Course.joins(:course_variants).where(:course_variants => {:variant_type => 1}).where("courses.id not in (?)",CourseVariant.where(:variant_type => 2).pluck(:course_id))
您可以在单个查询内部使用查询,这比上面的更快:
Course.joins(:course_variants).where(:course_variants => {:variant_type => 1}).where("courses.id not in (select course_id from course_variants where variant_type = 2)")
您可以通过在mysql的单个查询中使用group
来执行此操作:
Course.joins(:course_variants).group("course_variants.course_id").having("SUM(CASE WHEN variant_type = 1 THEN 1 WHEN variant_type = 2 THEN 2 ELSE 0 END) = 1")
如果您在Course和CourseVarint模型之间有关联,那么您可以执行以下操作:
Course.joins(:course_variants).where(course_variants: {variant_type: 1}).where.not(course_variants: {variant_type: 2})
- 在respond_with哈希中包含虚拟属性
- Rails 3 Active Record关系顺序:使用hash而不是string
- Rails 3.1限制用户创建的对象
- 无法创建新的Spree应用程序:“未定义的方法`raise_in_transactional_callbacks =’”
- ActiveRecord:inverse_of不适用于has_many:通过on上的连接模型
- 使ActiveRecord连接模型属性在查询结果中可用
- validation以确保唯一但忽略空值?
- 如何在ActiveRecord中进行自反的自我加入关系?
- ConnectionNotEstablished之后在JRuby中有一个multithreading环境