Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rails中的高级SQL_Sql_Ruby On Rails_Activerecord - Fatal编程技术网

Rails中的高级SQL

Rails中的高级SQL,sql,ruby-on-rails,activerecord,Sql,Ruby On Rails,Activerecord,我有两种型号 class User < AR has_many :friends end class Friend < AR # has a name column end class用户[“friends.name in(?),“Joe”,“Jack”],:group=>“users.id”),然后在数组中迭代以查找有两个朋友的用户 这是我为自己解决类似问题时得到的最佳解决方案。如果您找到了在纯sql或ActiveRecord中实现的方法,请告诉我 一个选项是将每个名称作

我有两种型号

class User < AR
 has_many :friends
end

class Friend < AR
  # has a name column
end
class用户
我需要找到所有与“Joe”和“Jack”都是朋友的用户


你知道我如何在rails中做到这一点吗?

可能的方法:
User.all(:joins=>:friends,:conditions=>[“friends.name in(?),“Joe”,“Jack”],:group=>“users.id”)
,然后在数组中迭代以查找有两个朋友的用户


这是我为自己解决类似问题时得到的最佳解决方案。如果您找到了在纯sql或ActiveRecord中实现的方法,请告诉我

一个选项是将每个名称作为单个内部联接的参数。在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'
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")
由于它是内部联接,因此它将仅显示可以同时使用f1和f2联接用户表的结果

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

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'
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")

尽管按照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查询的基础以获取用户模型实例。

对不起,我没有仔细阅读您的问题。。。删除了我不正确的答案。@muistooshort替换或由且不起作用您误解了我对Misha误解的更正,我们的评论也是这么说的。@muistooshort oh ya:)您对如何进行此查询有什么想法吗?您是否有任何特定的目标数据库?这很好,但此精确查询不起作用。查看使用此技术的其他解决方案。谢谢