0

次のような 3 つのモデルがあります (質問にとって重要なものを残しました)。

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 の場合は誰かがニーモニックに反対票を投じたことを意味します。

得票差上位3位までのニーモニックを取得したいと思います。データベースに 5 つのニーモニック レコードがあり、次の数の賛成/反対票があるとします (:vote_up フィールドとして true/false を持つ MnemonicVote レコード)。

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

次の 3 つのニーモニック (カウント付き) を降順で取得したいと思います。

mnemonic2  14
mnemonic4   4
mnemonic1   1

私はこの実際のコードを書いて、私が望む結果を得ましたが、それがひどいことを認識しており、特定のニーモニック レコードに関連付けられたすべての MnemonicVote レコードがフェッチされたにデータがグループ化およびソートされるため、その方法が好きではありません。 DB:

@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) クエリを使用して同じ結果を得たいと考えています。これはどのように達成できますか?ありがとう。

4

2 に答える 2

0

これがあなたが望むものだと思います:

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] }
于 2013-09-13T23:00:52.937 に答える
0

PostgreSQLで機能しなかったIF句を除いて、両方の答えは正しい軌道に乗っていました(関数 if(boolean, integer, integer) does not existを取得します)。誰かがそれを必要とする場合の私の最終的な解決策は次のとおりです。

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)
于 2013-09-14T06:29:35.557 に答える