2

我有一个模型视图:

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. 第三个问题是,当我尝试显示每小时和其他时间周期的计数时,它变得非常棘手,有人可以提出一个更好的解决方案,它也适用于日周期以外的其他时间周期吗?

基本上我正在制作一个包含在所有模型中的模块时间轴,以便轻松生成统计信息,例如:

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

谢谢!

4

1 回答 1

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)

这将从四月第一天的午夜到四月最后一天的午夜。有效地获取当月的所有数据。您可以通过删除月份参数来多年执行此操作,并通过添加天参数来执行几天。请参阅此处的用法。

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

3)自从我完成 SQL 以来已经有一段时间了,所以我不能真正给你确切的代码,但你总是可以尝试格式化你的日期输出,所以它包括小时/分钟/等,所以当它分组时,它会知道的。即使将其格式化为字符串也可以。一种效率较低的方法是为每个时间范围单独调用。

于 2012-07-17T16:13:45.940 回答