在rails数组中选择最大日期范围计数

时间:2015-07-31 01:30:36

标签: ruby-on-rails postgresql sorting ruby-on-rails-4

我有一个包含一堆deviceapi条目的数据库,它们有一个start_date和end_date(模式中的datetime)。通常这些条目的长度不超过20秒(end_date - start_date)。我有以下设置:

data = Deviceapi.all.where("start_date > ?", DateTime.now - 2.weeks)

我需要获得具有最高数量的Deviceapi条目的数据。为了使它更清晰一点,这是我最近的尝试(代码近似,不介意错别字):

runningtotal = 0
(2.weeks / 1.hour).to_i.times do |interval|
  current = data.select{ |d| d.start_time > (start_date + (1.hour * (interval - 1))) }.select{ |d| d.end_time < (start_date + (1.hour * interval)) }.count
  if current > runningtotal
    runningtotal = current
end

问题:这段代码运行得很好。关于它的十几个其他化身,使用.where,.select,SQL查询等也是如此。但它太慢了。 Waaaaay太慢了。因为它必须在2周内每小时循环一次。那么这个方法可能需要自己调用几十次。

必须有更快的方法来做到这一点,也许是一种?我很难过,而且我一直在寻找没有运气的好几个小时。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

为了获得足够的性能,您需要在单个查询中执行所有操作,这意味着要避免 ActiveRecord 功能并执行原始查询(例如,通过{{ 1}})。

我无法测试它,因为我既没有您的数据也没有架构,但我认为这些内容可以满足您的需求:

For Each result In query
   Msgbox(result.TABLENAME & "." & result.COLUMNNAME)
Next

从最内层的查询出来的逻辑如下:

  1. “Bucket”每个开始时间到小时
  2. 从生成的存储桶表中,获取每个存储桶中的条目总数
  3. 从该表中获取最大条目数,然后使用该数字匹配以获取starting_hour本身。
  4. 如果恰好有多个条目具有相同数量的条目,您可以确定一致的方式来选择一个 - 比如ActiveRecord::Base.connection.execute或类似(因为即使数据得到,它也会保持不变添加,假设您没有删除项目。)

    如果您想限制初始时间片 - 我发现您的帖子中提到了2周 - 您可以在最里面的查询中执行此操作,并使用select y.starting_hour, max(y.num_entries) as max_entries from ( select x.starting_hour, count(*) as num_entries from ( select date_trunc('hour', start_time) starting_hour from deviceapi as d ) as x group by x.starting_hour ) as y where y.num_entries = max(y.num_entries); 子句将日期范围括起来。

相关问题