3

私は2つのクラスを持っています:

class Solution
  has_many :solution_votes

class SolutionVote
  belongs_to :solution

私の見解では、次のようなものがあります。


    Proposed Solution A - 2 votes up - 5 votes down
    Proposed Solution B - 1 vote up  - 0 votes down
    Proposed Solution C - 0 votes up - 0 votes down
    Proposed Solution D - 7 votes up - 2 votes down
    Proposed Solution E - 3 votes up - 1 vote down
     

私が望むのは、これを最も多くのUP投票でソートして、代わりに次のようにすることです:


    Proposed Solution D - 7 votes up - 2 votes down
    Proposed Solution E - 3 votes up - 1 vote down
    Proposed Solution A - 2 votes up - 5 votes down
    Proposed Solution B - 1 vote up  - 0 votes down
    Proposed Solution C - 0 votes up - 0 votes down
    

私はこれまでのところこれを持っています:

 scope :most_votes_up,
  select("solutions.*, count(solution_votes.id) AS votes_count").
      where(['solutions.state = ?', 'Proposed']).
      joins(:solution_votes).
      group("solutions.id").
      order("votes_count DESC")

次の出力が生成されます。


    Proposed Solution D - 7 votes up - 2 votes down
    Proposed Solution A - 2 votes up - 5 votes down
    Proposed Solution E - 3 votes up - 1 vote down
    Proposed Solution B - 1 vote up  - 0 votes down
    

しかし...私がまだ抱えている問題は次
のとおりです
。投票(現在、どの提案されたソリューションが最も多くの票(賛成票と反対票の両方)を獲得したかに基づいて順序付けられています)?

私はPostGRESQLを使用しています

4

1 に答える 1

3
  1. 左結合 (デフォルトの内部結合の代わりに) を使用して、関連する solution_votes が 0 のソリューションを含めます。

  2. カウントに賛成票のみを含めることができます。

スコープを修正する方法は次のとおりです。

select("solutions.*, count(solution_votes.id) AS votes_count").
  joins("left join solution_votes on solution_votes.solution_id = solutions.id").
  where(['solutions.state = ? and solution_votes.direction = ?', 'Proposed', 'up']).
  group("solutions.id").
  order("votes_count DESC")

これにより、列名についていくつかの仮定が立てられますが、実際のスキーマに合わせて問題なく調整できるはずです。joins前にもwhere述べましたが、これは技術的に違いはありませんが、SQL が必要とする順序であり、私にとってより論理的な意味を持ちます。

編集:votes_countをすべての投票の数として保持したいように聞こえますが、それでも賛成票の数で並べ替えます。返された Solution オブジェクトを呼び出していない限り、その理由はわかりませんが.votes_count、可能です。これを行うには、count集約からsumに切り替えてから、カウントしたい条件に一致するレコードを 1 として扱い、一致しないレコードを 0 として扱う何かを行いますcasesum(case when solution_votes.direction = 'up' then 1 else 0 end)ブール値を整数に変換するための創造的なキャストsum(cast(solution_votes.direction = 'up' as integer))。これらは両方とも機能します。合計が賛成票の合計数になり、それを order 句で使用できます。最初のものを選択すると、特に理由はありませんが、次の改訂された範囲になります。

select("solutions.*, count(solution_votes.id) AS votes_count, sum(case when solution_votes.direction = 'up' then 1 else 0 end) as up_votes").
  joins("left join solution_votes on solution_votes.solution_id = solutions.id").
  where(['solutions.state = ? and solution_votes.direction = ?', 'Proposed', 'up']).
  group("solutions.id").
  order("up_votes DESC")
于 2012-07-21T05:07:18.983 に答える