通过named_scope返回对象数组 - has_many ... belongs_to association; UNION ALL查询

时间:2011-02-06 19:41:44

标签: sql mysql ruby-on-rails named-scope

我正在寻找一个答案,它将通过(最好)一个named_scope返回一个用户对象数组,或者通过User模型上的类方法返回一些操作。

所以没有进一步的... ...

我有两个表:用户和战斗。

  • 用户有很多打架(has_many:打架,:foreign_key =>'challenger_id或challengee_id')
  • 战斗属于用户(belongs_to:challenger,:class_name =>'用户'... belongs_to:challengee,:class_name =>'用户')

战斗有以下几个关注的栏目:

  • challenger_id(user_id fk)
  • challengee_id(user_id fk)
  • challenger_won(boolean)

正如您所看到的,用户可以是挑战者或挑战者,但不能同时是两者。

  • 如果用户是挑战者并且challenger_won = true,那么它将被视为胜利。
  • 如果用户是挑战者且challenger_won = false,则认为是胜利。
  • 如果challenger_won = null,则忽略它。

我有一个原始SQL语句,它返回按最多wins属性分组的战斗机属性(user_id):

SELECT a.fighter, COUNT(*) AS wins
  FROM (SELECT challenger_id AS fighter
          FROM fights
         WHERE challenger_won = TRUE
        UNION ALL
        SELECT challengee_id AS fighter
          FROM fights
         WHERE challenger_won = FALSE
       ) AS a
 GROUP BY a.fighter;

所以给定这个信息,我如何通过(最好)一个named_scope返回一个用户对象数组,或者通过用户模型上的类方法做一些操作?

2 个答案:

答案 0 :(得分:4)

我认为您可以尝试这样的方法来重新创建查询结果:

class User
    named_scope :winners, 
        :select => 'users.*, COUNT(fight.id) AS wins', 
        :join => :fights,  
        :conditions => ['(fights.challenger_id = user_id AND fights.challenger_won = TRUE) OR (fights.challengee_id = user_id AND NOT fights.challenger_won = FALSE)']
        :group => 'user_id'
end

但是,对于缓存目的,您可能需要考虑将win_count字段添加到User模型。如果你为战斗的胜利者创建了一个setter方法,你可以在它改变的那一刻增加win_count。

答案 1 :(得分:0)

或者,没有连接(特定于mysql)

class User
  named_scope :winners, 
    :select => 'if(challenger_won = FALSE,challenger,challengee) as winner,COUNT(id) AS wins ', 
    :group => 'user_id'
end