【问题标题】:Parent entity sorted by votes difference按票数差异排序的父实体
【发布时间】:2013-09-18 17:26:31
【问题描述】:

我有三个看起来像这样的模型(我只留下了对问题很重要的东西):

class Symbol < ActiveRecord::Base
  has_many :mnemonic
end

class Mnemonic < ActiveRecord::Base
  belongs_to :symbol
  has_many :mnemonic_votes
end

class MnemonicVote < ActiveRecord::Base
  belongs_to :mnemonic
  attr_accessible :vote_up
end

:vote_up 是布尔类型,如果为 true,则表示有人赞成助记符,如果为 false,则表示有人反对。

我想通过投票差获得前三名的助记符。假设数据库中有 5 条助记词记录,其赞成/反对票数如下(MnemonicVote 记录的 true/false 为 :vote_up 字段):

mnemonic      up   down  total
mnemonic1      3     2     1
mnemonic2     17     3    14
mnemonic3      2     5    -3
mnemonic4     11     7     4
mnemonic5      5     5     0

我想按降序得到以下三个助记词(带计数):

mnemonic2  14
mnemonic4   4
mnemonic1   1

我编写了这段实际代码,它给了我想要的结果,但我知道它很糟糕,我不喜欢我的做法,因为数据在所有 MnemonicVote 之后被分组和排序从数据库中获取与某个助记符记录相关的记录:

@mnemonics = Mnemonic.where(symbol_id: self.id)   # here I fetch all Mnemonics associated with Symbol table
@mnemonics.sort_by { |mnemonic| mnemonic.votes_total }.reverse!
return @mnemonics.take(3)

其中 mnemonic.votes_total 是 Mnemonic 对象的计算属性。我想通过使用单个 AR(甚至 SQL)查询来获得相同的结果。如何实现?谢谢。

【问题讨论】:

    标签: sql ruby postgresql activerecord ruby-on-rails-3.2


    【解决方案1】:

    我相信这就是你想要的:

    Mnemonic.
      joins(:mnemonic_votes).
      select("mnemonics.*, SUM(IF(mnemonic_votes.upvote, 1, -1)) AS vote").
      group("mnemonics.id").
      order("vote DESC").
      map { |m| [m.symbol, m.vote.to_i] }
    

    【讨论】:

    • 谢谢你,让我走上了正轨,虽然 IF 子句因为 PostgreSQL 而不能那样工作。
    【解决方案2】:

    两个答案都在正确的轨道上,除了不适用于 PostgreSQL 的 IF 子句(我会得到 function if(boolean, integer, integer) 不存在)。如果有人需要,这是我的最终解决方案:

    Mnemonic.
      select("mnemonics.*, SUM(CASE WHEN mnemonic_votes.vote_up THEN 1 ELSE -1 END) AS votes_total").
      joins(:mnemonic_votes).
      where(symbol_id: self.id).
      group("mnemonics.id").
      order("votes_total DESC").
      limit(3)
    

    【讨论】:

      猜你喜欢
      • 2011-04-14
      • 2011-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-29
      • 2016-07-13
      • 1970-01-01
      相关资源
      最近更新 更多