按列对数据库查询排序,然后随机排序

时间:2015-04-15 17:06:28

标签: sql ruby-on-rails postgresql

假设您有一个具有投票属性的项目模型。这可能是一些示例数据:

Item, Votes
-----------
Red     4
Blue    5
Black   5   
Green   4
Cyan    5
Yellow  4
Orange  4

我想要一个首先通过投票对其进行排序的范围:

Item, Votes
-----------
Orange  4
Green   4
Yellow  4
Red     4
Blue    5
Black   5   
Cyan    5

然后在每个投票队列中随机化:

Item, Votes
-----------
Green   4
Red     4
Orange  4
Yellow  4
Black   5   
Blue    5
Cyan    5

然后将其限制为前两个结果。

我试过这个:

scope :options, -> { order('random()').order("votes asc").limit 2 }

和此:

scope :options, -> { order("votes asc").order('random()').limit 2 }

但两者都没有按预期工作。第一个版本似乎是完全随机的,第二个版本根本不是随机的。

3 个答案:

答案 0 :(得分:1)

根据您的具体需求,您有两种选择。如果您想要完整结果中的前两个(下面突出显示),那么您的第二个解决方案将起作用。但是,如果您想要每个组的第一行,您需要稍微修改一下您的查询(如下所示:)


完整结果的第一行:

scope :options, -> { order('votes ASC, random()').limit(2) }

将选择以下行:

Item, Votes
-----------
Green   4  *
Red     4  *
Orange  4
Yellow  4
Black   5   
Blue    5
Cyan    5

每组的第一行:

scope :options, -> { select('DISTINCT ON (votes) *').order('votes ASC, random()').limit(2) }

将选择以下行:

Item, Votes
-----------
Green   4  *
Red     4
Orange  4
Yellow  4
Black   5  *   
Blue    5
Cyan    5

答案 1 :(得分:0)

就分拣而言,有一个很棒的宝石叫做“Ransack”' (https://github.com/activerecord-hackery/ransack)允许动态排序数据集。我担心自己无法提供其他问题,但希望这有助于排序!

答案 2 :(得分:0)

在项目模型中我制作了这个方法:

def rand_value
  self.votes + Random.rand
end

然后在控制器中我使用此查询:

@items = @experiment.items.sort_by { |item| [item.rand_value] }

这似乎像我想要的那样工作。列表中的第一项始终是投票率最低的项目,但在每个队列中,它们都是随机的。唯一的缺点是它不仅限于两个结果。