【问题标题】:"NOT IN" for Active RecordActive Record 的“NOT IN”
【发布时间】:2016-08-09 20:54:08
【问题描述】:

我有一个 MySQL 查询,我试图在它的末尾链接一个“NOT IN”。

这是使用 Active Record 在 ruby​​ 中的样子:

not_in = find_by_sql("SELECT parent_dimension_id FROM relations WHERE relation_type_id  = 6;").map(&:parent_dimension_id)

      joins('INNER JOIN dimensions ON child_dimension_id = dimensions.id')
          .where(relation_type_id: model_relation_id,
                 parent_dimension_id: sub_type_ids,
                 child_dimension_id: model_type)
          .where.not(parent_dimension_id: not_in)

所以我尝试执行的 SQL 查询如下所示:

INNER JOIN dimensions ON child_dimension_id = dimensions.id
WHERE relations.relation_type_id = 5 
AND relations.parent_dimension_id 
NOT IN(SELECT parent_dimension_id FROM relations WHERE relation_type_id  = 6);

有人可以向我确认该查询应该使用什么吗? 我应该链接 where.not 吗?

【问题讨论】:

    标签: mysql ruby-on-rails ruby rails-activerecord active-record-query


    【解决方案1】:

    如果你真的想要

    SELECT parent_dimension_id
    FROM relations
    WHERE relation_type_id = 6
    

    作为子查询,您只需将该 SQL 转换为 ActiveRecord 关系:

    Relation.select(:parent_dimension_id).where(:relation_type_id => 6)
    

    然后将其用作 where 调用中的值,就像使用数组一样:

    not_parents = Relation.select(:parent_dimension_id).where(:relation_type_id => 6)
    
    Relation.joins('...')
            .where(relation_type_id: model_relation_id, ...)
            .where.not(parent_dimension_id: not_parents)
    

    当您使用 ActiveRecord 关系作为 where 中的值并且该关系选择单个列时:

    r = M1.select(:one_column).where(...)
    M2.where(:column => r)
    

    ActiveRecord 足够聪明,可以将 r 的 SQL 内联为 in (select one_column ...),而不是执行两个查询。

    你可能会替换你的:

    joins('INNER JOIN dimensions ON child_dimension_id = dimensions.id')
    

    如果您的关系也已建立,则使用更简单的joins(:some_relation)

    【讨论】:

      【解决方案2】:

      您可以为 where 子句提供值或值数组,在这种情况下,它们将被转换为 in (?) 子句。

      因此,查询的最后一部分可能包含一个映射:

      .where.not(parent_dimension_id:Relation.where(relation_type_id:6).map(&:parent_dimension_id))
      

      或者你可以准备一份声明

      .where('parent_dimension_id not in (?)', Relation.where(relation_type_id:6).map(&:parent_dimension_id) )
      

      本质上是一回事

      【讨论】:

      • 如果您 where.not(parent_dimension_id: Relation.where(...).select(:parent_dimension_id)) AR 将使用子查询 (parent_dimension_id not in (select parent_dimension_id from ...)) 而不是两个带有中间 Ruby 数组的查询。
      • 我没有测试过这个,但你显然是对的。把这个作为答案,我会放弃我的:)
      猜你喜欢
      • 2014-11-15
      • 1970-01-01
      • 1970-01-01
      • 2017-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-14
      • 1970-01-01
      相关资源
      最近更新 更多