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
    

但是......我仍然遇到的问题是:
1.没有投票的建议解决方案丢失(上面示例中的建议解决方案C从显示的列表中丢失)
2.我如何指定仅对UP的计数投票(现在,它的排序基于哪个提议的解决方案获得了最多的投票(上下),而不仅仅是上升)?

我正在使用 PostGRESQL

4

1 回答 1

3
  1. 使用左连接(而不是默认的内连接)来包含具有 0 个关联的 solution_votes 的解决方案。

  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 保留为所有选票的计数,但仍按赞成票数排序。我不确定为什么会这样,除非您调用.votes_count返回的解决方案对象,但这是可能的。为了做到这一点,您从count聚合切换到sum,然后执行一些操作,将匹配条件的记录视为 1,将不匹配的记录视为 0。两种方式呈现自己,一个case表达式,like sum(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 回答