按排名和总数排序,其中可能存在多个条目

时间:2015-04-21 20:13:19

标签: ruby-on-rails activerecord

Ruby 2.1.5
Rails 4.2.1

我的模型是贡献,包含以下字段:

event, contributor, date, amount

表格会是这样的:

earth_day, joe, 2014-04-14, 400
earth_day, joe, 2015-05-19, 400
lung_day, joe, 2015-05-20, 800
earth_day, john, 2015-05-19, 600
lung_day, john, 2014-04-18, 900
lung_day, john, 2015-05-21, 900

我构建了一个显示所有这些字段的索引视图,并通过单击“索引”视图中的列标题实现了排序(和反向顺序)的代码。

我要做的是将Index视图显示如下:

Event    Contributor    Total    Rank

如果每个贡献者仅列出一次事件,并且总数是贡献者对此事件的所有贡献的总和,则排名是此贡献者相对于此特定事件的所有其他人的排名。

我正在玩一个单独的表,其中只为每个事件/贡献者保留一个运行的计数器和一段代码来计算排名并将其重新插入表中,然后使用该表来驱动视图。

你能想到更好的方法吗?

1 个答案:

答案 0 :(得分:1)

保持运行记录是一个不错的选择。写入速度会变慢,但读取速度会很快。

另一种方法是创建数据库视图,如果您使用的是postgresql,例如:

-- Your table structure and data
create table whatever_table (event text, contributor text, amount int);
insert into whatever_table values ('e1', 'joe', 1);
insert into whatever_table values ('e2', 'joe', 1);
insert into whatever_table values ('e1', 'jim', 0);
insert into whatever_table values ('e1', 'joe', 1);
insert into whatever_table values ('e1', 'bob', 1);

-- Your view
create view event_summary as (
  select
    event,
    contributor,
    sum(amount) as total,
    rank() over (order by sum(amount) desc) as rank
  from whatever_table
  group by event, contributor
);

-- Using the view
select * from event_summary order by rank;
 event | contributor | total | rank
-------+-------------+-------+------
 e1    | joe         |     2 |    1
 e1    | bob         |     1 |    2
 e2    | joe         |     1 |    2
 e1    | jim         |     0 |    4
(4 rows)

然后你有一个ActiveRecord类,如:

class EventSummary < ActiveRecord::Base
  self.table_name = :event_summary
end

您可以执行EventSummary.order(rank: :desc)之类的操作,等等。这不会减慢写入速度,但读取速度会慢一些,具体取决于您使用的数据量。

Postgresql还支持物化视图,假设在输入数据和更新汇总表之间可能会有一点滞后,这可以为您提供两全其美的优势。