【问题标题】:Advanced SQL in RailsRails 中的高级 SQL
【发布时间】:2012-05-21 04:31:01
【问题描述】:

我有 2 个模型

class User < AR
 has_many :friends
end

class Friend < AR
  # has a name column
end

我需要找到所有与“Joe”和“Jack”都是朋友的用户

知道如何在 Rails 中做到这一点吗?

【问题讨论】:

  • 对不起,我没有仔细阅读您的问题...删除了我的错误答案。
  • @muistooshort 替换 or 并且不起作用
  • 你误解了我对Mischa误解的更正,我们的cmets说的是同样的话。
  • @muistooshort oh ya :) 任何想法如何进行此查询?
  • 你有什么特定的目标数据库吗?

标签: sql ruby-on-rails activerecord


【解决方案1】:

一种选择是将每个名称作为单独的 INNER JOINS 的参数。在 SQL 中会是这样的:

SELECT users.* FROM users
INNER JOIN friends AS f1 
    ON users.id = f1.user_id 
    AND f1.name = 'Joe'
INNER JOIN friends AS f2 
    ON users.id = f2.user_id 
    AND f2.name = 'Jack'

由于是INNER JOINS,所以只会显示users表同时f1和f2都可以join的结果。

要在 Rails 中使用它,可以这样做:

class User < AR
  has_many :friends

  def self.who_knows(*friend_names)
    joins((1..friend_names.length).map{ |n| 
      "INNER JOIN friends AS f#{n} ON users.id = f#{n}.user_id AND f#{n}.name = ?" }.join(" "),
      *friend_names)
    })
  end
end

然后你可以这样调用:

@users = User.who_knows("Joe", "Jack")

【讨论】:

    【解决方案2】:

    可能的方式:User.all(:joins =&gt; :friends, :conditions =&gt; ["friends.name IN (?,?)", "Joe", "Jack"], :group =&gt; "users.id") 然后遍历数组找到有 2 个朋友的用户。

    这是我尝试为自己解决类似问题时得到的最佳解决方案。如果您找到使用纯 sql 或 ActiveRecord 的方法 - 请告诉我!

    【讨论】:

      【解决方案3】:

      虽然按照 DanneManne 的建议使用硬编码 SQL 最常见,并且可能是您想要的方式,但它不一定是可组合的。一旦您硬编码了一个表名,您可能会遇到将其组合到 ActiveRecord 可能决定为该表别名的其他查询的问题。

      因此,以一些额外的复杂性为代价,我们可以使用一些 ARel 来解决这个问题,如下所示:

      f = Friend.arel_table
      User.
        where(:id=>f.project(:user_id).where(f[:name].eq('Joe'))).
        where(:id=>f.project(:user_id).where(f[:name].eq('Jack')))
      

      这将使用一对子查询来完成这项工作。

      我相当肯定还有一个使用连接的 ARel 解决方案,但是我可以弄清楚如何在 ARel 中编写该查询,只是不知道如何使用该查询作为 ActiveRecord 查询的基础来取回用户模型实例。

      【讨论】:

      • 这很好,但是这个确切的查询不起作用。查看使用此技术的其他解决方案。谢谢!
      猜你喜欢
      • 2015-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-05
      • 1970-01-01
      • 2014-02-26
      相关资源
      最近更新 更多