How can I create active relation queries in Rails 3 that are aggregated by time slice?
如何在Rails 3中创建由时间片聚合的活动关系查询?
I'd like to build queries that for every n minute interval can return min, max, avg, sum, count, for every sample of a counter with a particular name.
我想建立一个查询,每隔n分钟可以为具有特定名称的计数器的每个样本返回min,max,avg,sum,count。
create_table "samples"
t.integer "counter_id"
t.string "name"
t.float "value"
t.datetime "created_at"
end
2 个解决方案
#1
4
Unfortunately I've never used Postgres, so this solution works in MySQL. But I think you can find out Postgres analogs.
不幸的是我从未使用过Postgres,所以这个解决方案适用于MySQL。但我认为你可以找到Postgres类似物。
class Counter < ActiveRecord::Base
has_many :samples do
# default 30 minutes
def per_time_slice(slice = 30)
start = "2000-01-01 00:00:00"
self.select("*,
CONCAT( FLOOR(TIMESTAMPDIFF(MINUTE,'#{start}',created_at)/#{slice})*#{slice},
(FLOOR(TIMESTAMPDIFF(MINUTE,'#{start}',created_at)/#{slice})+1)*#{slice} ) as slice,
avg(value) as avg_value,
min(value) as min_value,
max(value) as max_value,
sum(value) as sum_value,
count(value) as count_value").
group("slice").order("slice")
end
end
end
Usage
counter = find_some_counter
samples = counter.samples.per_time_slice(60).where(:name => "Bobby")
samples.map(&:avg_value)
samples.map(&:min_value)
samples.map(&:max_value)
etc
#2
1
This should do the trick:
这应该是诀窍:
Samples.where("SQL for the time slice goes here").where(:name, "Views").average(:value)
You can also swap average for any of minimum, maximum and sum.
您还可以将平均值换成最小值,最大值和总和。
#1
4
Unfortunately I've never used Postgres, so this solution works in MySQL. But I think you can find out Postgres analogs.
不幸的是我从未使用过Postgres,所以这个解决方案适用于MySQL。但我认为你可以找到Postgres类似物。
class Counter < ActiveRecord::Base
has_many :samples do
# default 30 minutes
def per_time_slice(slice = 30)
start = "2000-01-01 00:00:00"
self.select("*,
CONCAT( FLOOR(TIMESTAMPDIFF(MINUTE,'#{start}',created_at)/#{slice})*#{slice},
(FLOOR(TIMESTAMPDIFF(MINUTE,'#{start}',created_at)/#{slice})+1)*#{slice} ) as slice,
avg(value) as avg_value,
min(value) as min_value,
max(value) as max_value,
sum(value) as sum_value,
count(value) as count_value").
group("slice").order("slice")
end
end
end
Usage
counter = find_some_counter
samples = counter.samples.per_time_slice(60).where(:name => "Bobby")
samples.map(&:avg_value)
samples.map(&:min_value)
samples.map(&:max_value)
etc
#2
1
This should do the trick:
这应该是诀窍:
Samples.where("SQL for the time slice goes here").where(:name, "Views").average(:value)
You can also swap average for any of minimum, maximum and sum.
您还可以将平均值换成最小值,最大值和总和。