【问题标题】:Rails: join with multiple conditionsRails:加入多个条件
【发布时间】:2011-03-21 11:16:31
【问题描述】:

我有一个简单的模型,比如

class Interest < ActiveRecord::Base
  has_and_belongs_to_many :user_profiles
end

class UserProfile < ActiveRecord::Base
  has_and_belongs_to_many :interests
end

当我想查询所有具有特定兴趣的用户时,这很简单

UserProfile.joins(:interests).where('interests.id = ?', an_interest)

但是我怎样才能找到有多种兴趣的用户呢?当然如果我这样做了

UserProfile.joins(:interests).where('interests.id = ?', an_interest).where('interests.id = ?', another_interest)

我总是得到一个空结果,因为在加入之后,任何行都不能同时具有 interest.id = an_interest 和 interest.id = another_interest。

ActiveRecord 中有没有办法表达“我想要关联 2 个(指定)兴趣的用户列表?

更新(解决方案)这是我提出的第一个工作版本,感谢 Omar Qureshi

    specified_interests.each_with_index do |i, idx|
      main_join_clause = "interests_#{idx}.user_profile_id = user_profiles.id"
      join_clause = sanitize_sql_array ["inner join interests_user_profiles interests_#{idx} on
                    (#{main_join_clause} and interests_#{idx}.interest_id = ?)", i]

      relation = relation.joins(join_clause)
    end

【问题讨论】:

    标签: ruby-on-rails-3 activerecord join


    【解决方案1】:

    in (?) 不好 - 它是一个类似 OR 的表达式

    您需要做的是长期编写多个连接

    profiles = UserProfile
    interest_ids.each_with_index do |i, idx|
      main_join_clause = "interests_#{idx}.user_profile_id = user_profiles.id"
      join_clause = sanitize_sql_array ["inner join interests interests_#{idx} on
                            (#{main_join_clause} and interests_#{idx}.id = ?)", i]
      profiles = profiles.join(join_clause)
    end
    profiles
    

    您可能需要更改 main_join_clause 以满足您的需要。

    【讨论】:

    • 这比我希望的要复杂得多:)!但你肯定给我指出了正确的方向。谢谢。唯一的区别是我必须inner join interests_user_profiles 而不是你写的inner join interests
    • ...并将interests_#{idx}.id = ?替换为interests_#{idx}.interest_id = ?
    • 啊,对 - 这是 M 对 M 连接?这是有道理的,抱歉没有读到那一点! :D
    【解决方案2】:

    这将获得至少具有指定兴趣之一的用户。

    UserProfile.joins(:interests).where(:id => [an_interest_id, another_interest_id])
    

    为了让用户同时拥有指定的兴趣,我可能会这样做:

    def self.all_with_interests(interest_1, interest_2)
      users_1 = UserProfile.where("interests.id = ?", interest_1.id)
      users_2 = UserProfile.where("interests.id = ?", interest_2.id)
    
      users_1 & users_2
    end
    

    效率不高,但应该可以满足您的需求?

    【讨论】:

    • 我试过UserProfile.joins(:interests).where("interests.id = ?" , [25, 26])但没用
    • 不,它仍然不起作用。我在查询SELECT "user_profiles".* FROM "user_profiles" INNER JOIN "interests_user_profiles" ON "interests_user_profiles"."user_profile_id" = "user_profiles"."id" INNER JOIN "interests" ON "interests"."id" = "interests_user_profiles"."interest_id" WHERE (interests.id = 25,26) 中遇到语法错误
    • 我刚刚阅读了您对另一个答案的评论 - 我没有意识到您需要一个逻辑与。我的回答会做 OR。
    【解决方案3】:

    试试IN (?) 和一个数组:

    UserProfile.joins(:interests).where('interests.id IN (?)', [1,2,3,4,5])
    

    【讨论】:

    • IN 子句进行逻辑 OR(具有一个兴趣或另一个或两者)...我需要一个逻辑 AND(具有所有兴趣)
    猜你喜欢
    • 1970-01-01
    • 2013-07-22
    • 2013-08-03
    • 1970-01-01
    • 2016-03-06
    • 2013-04-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多