我有2种型号高级SQL Rails中
class User < AR
has_many :friends
end
class Friend < AR
# has a name column
end
我需要找到谁是既“乔”和朋友们所有用户的“杰克”
任何想法我如何能在轨道做到这一点?
我有2种型号高级SQL Rails中
class User < AR
has_many :friends
end
class Friend < AR
# has a name column
end
我需要找到谁是既“乔”和朋友们所有用户的“杰克”
任何想法我如何能在轨道做到这一点?
一种选择是将每个名称作为单个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'
既然是内部联接,它只会显示效果在用户表可以同F1和F2结合。
而且在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")
可能的方法:User.all(:joins => :friends, :conditions => ["friends.name IN (?,?)", "Joe", "Jack"], :group => "users.id")
然后遍历数组以找到有2个朋友的用户。
这是我尝试为自己解决类似问题时得到的最佳解决方案。如果你在纯sql或ActiveRecord中找到方法 - 请告诉我!
虽然使用硬编码的SQL由DanneManne的建议通常会工作,而且可能是你想要去的方式,它不一定是可组合的。只要你对表名进行了硬编码,你就会遇到一些问题,将其结合到其他查询中,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查询的基础来取回用户模型实例。
这很棒,但这个确切的查询不起作用。看看使用这种技术的其他解决方案。谢谢! –
对不起,我没有仔细阅读您的问题......删除了我的不正确答案。 – Mischa
@ muistooshort替换或者不工作 –
您误解了我对Mischa误解的纠正,我们的评论也是这样说的。 –