如何在 Rails 3 中按时间片(总和、平均值、最小值、最大值等)获取聚合数据

发布于 2024-10-20 02:57:20 字数 264 浏览 2 评论 0原文

如何在 Rails 3 中创建按时间片聚合的活动关系查询?

我想构建查询,对于具有特定名称的计数器的每个样本,每 n 分钟间隔可以返回最小值、最大值、平均值、总和、计数。

create_table "samples"  
    t.integer  "counter_id"  
    t.string "name"  
    t.float    "value"  
    t.datetime "created_at"  
end  

How can I create active relation queries in Rails 3 that are aggregated by time slice?

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.

create_table "samples"  
    t.integer  "counter_id"  
    t.string "name"  
    t.float    "value"  
    t.datetime "created_at"  
end  

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

橘香 2024-10-27 02:57:20

不幸的是我从未使用过 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

用途

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)

Unfortunately I've never used Postgres, so this solution works in MySQL. But I think you can find out Postgres analogs.

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

任性一次 2024-10-27 02:57:20

这应该可以解决问题:

Samples.where("SQL for the time slice goes here").where(:name, "Views").average(:value)

您还可以将平均值交换为最小值、最大值和总和中的任何一个。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文