3

假设我有模型:用户和项目以及它们之间的多对多关系。如何获得具有已定义属性的确切(不再)项目的用户,即具有颜色 = ['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 语法中做到这一点?

4

1 回答 1

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 种不同颜色项目的用户

这意味着您需要:

candidate_users.reject! do |candidate| 
  candidate.items.map {|item| item.color}.sort != ['black', 'red']
end

您可能可以完全消除这里对 ruby​​ 的需求,但 SQL 会变得丑陋七种。(交叉连接,哦,我的...)

于 2009-03-31T08:02:36.280 回答