假设我有模型:用户和项目以及它们之间的多对多关系。如何获得具有完全(不再)具有已定义属性的项目的用户,即具有颜色= ['red','black']的项目的用户。
当然我可以这样做:
User.all :joins => [:items, :items], :conditions => {:"items.color" => "red", :"items_users.color" => 'black'}
但是对于更多属性来说,这将非常麻烦。 我也可以这样做:
User.all(:conditions => ["items.color in (?), ['red', 'black']], :include => :items)
但是这个用户还会返回颜色为[''red','black','blue','etc']
的项目的用户所以唯一的解决方案是获取所有并使用ruby语法排序?如何在一个SQL查询或Rails AR语法中执行此操作?
答案 0 :(得分:1)
在我看来,优化程序员时间和可读性的方法:
#get all users who have items which are both red and black but no other colors
candidate_users = User.all(:include => :items)
candidate_users.reject! do |candidate|
candidate.items.map {|item| item.color}.sort != ['black', 'red']
end
如果您希望在那里循环使用公制卡车的用户,那么您需要对其进行SQL编写。警告:SQL不是我的包,宝贝:使用前测试。
select users.*, items.* FROM users
INNER JOIN items_users ON (items_users.user_id = users.id)
INNER JOIN items ON (items_users.item_id = items.id)
GROUP BY users.id HAVING COUNT(DISTINCT items.color) = 2
我认为邪恶的混乱:
1)抓住每个用户/项目组合 2)向具有2种不同颜色项目的用户进行Winnows
这意味着你需要:
candidate_users.reject! do |candidate|
candidate.items.map {|item| item.color}.sort != ['black', 'red']
end
你可以完全消除对红宝石的需求,但SQL会有七种难看的味道。 (Cross加入,哦,我的...)