我有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誤解的糾正,我們的評論也是這樣說的。 –