按小时,日,月和年生成计数统计

时间:2012-07-17 13:48:35

标签: ruby-on-rails activerecord

我有一张表模型查看:

View(id: integer, created_at: datetime)

我想在一段时间内生成每小时,日,月或年的观看次数,以便在图表上使用它们。我已经做了类似的事情:

View.group('DATE(views.created_at)')
    .select("*, count(*) AS series_count, DATE(views.created_at) AS series_time")
    .where(:created_at => (Time.now-7.days)..Time.now)

这导致:

2012-06-16 => 20
2012-06-17 => 12
2012-06-18 => 15
2012-06-20 => 38 # Issue: Didn't include a day with no records
2012-06-21 => 11
2012-06-22 => 76
  1. 第一个问题是,它不会将填充添加到减去天数或月数或没有记录的任何内容。

  2. 第二个问题是,有时会增加另一天,导致8天!

  3. 第三个问题是,当我尝试显示每小时和其他时间周期的计数时,它变得非常棘手,有人可以建议一个更好的解决方案,但也适用于非日间周期吗?

  4. 基本上我正在创建一个模块时间轴,它包含在所有模型中,以便轻松生成数据:

    include Timeline # on the model
    Model.timeline(
          :time_column => :created_at,
          :period => (Time.now-24.hours)..Time.now,
          :by => :hours
        )
    

    谢谢!

1 个答案:

答案 0 :(得分:0)

1)有很多方法可以解决这个问题,但我不确定哪个更有效率。所有这些都包括首先制作一个您想要显示的日期数组,然后在结果子集中添加不包含的内容,或者将从数据库中获取的内容插入到地图中。我做了类似的事情,以便在一段时间内制作预期时间的数组:

class Time

  #Period is the number of seconds between each interval 
  def upto(end_time, period)

    division_count = (end_time.to_i - self.to_i) / period

    divisions = division_count.times.map { |div| self + (period * div) }

    divisions << end_time

  end

  #Period is the number of seconds between each interval 
  def downto(start_time, period)

    division_count = (self.to_i - start_time.to_i) / period

    divisions = division_count.times.map { |div| start_time + (period * div) }
    divisions

  end

end

要获取两天之间的天数,请按以下方式调用:

time_one.upto(time_two, 1.day.to_i)

警告:这将包括两天。要获得7天的续航时间,请从time_two中删除一天。

time_one.upto(time_two - 1.day, 1.day.to_i

2)这个问题是你需要花时间而不是最后一小时。你需要回到最后一天/小时/分钟,然后从中减去。对于天数之间的范围,您可以在2012年4月份这样做:

Time.utc(2012, 04)..Time.utc(2012, 05)

这将从四月的第一天午夜到四月的最后一天的午夜。有效获取该月的所有数据。您可以通过添加day参数来删除月份参数和数天来执行此操作多年。 See usage here.

几个小时,它有点复杂。您可以创建一个新的日期,只将您想要保留的日期转移到新日期,从而剥离您不需要的内容,然后从中减去。

3)自从我完成SQL以来已经有一段时间了,所以我无法真正为您提供相应的代码,但您可以随时尝试设置日期输出的格式,以便包括小时/分钟/等等。它会分组,它会知道的。即使将其格式化为字符串也行。一种效率较低的方法是为每个时间范围单独调用。