按4小时间隔分组

时间:2014-03-24 22:31:53

标签: ruby-on-rails ruby postgresql

我试图在4小时内获得一些数据的平均值,我的应用程序是在Ruby on Rails中,所以我不知道是否应该编写PostgreSQL查询或者执行此操作在应用程序模型中,我也不知道如何在其中执行此操作。 模型的简单版本是这样的:

id    heart_rate    timestamp

我还需要1小时和1天的间隔但我已经知道如何做到这一点,至少在SQL方面:

SELECT AVG(heart_rate), to_char(timestamp, 'YYYY-MM-DD') AS ts
FROM vital_signs
GROUP BY ts
ORDER BY ts ASC;

3 个答案:

答案 0 :(得分:1)

24小时/ 4 = 6段。

将您的日期转换为小时,然后执行整数除法(DIV)。这将给你0-5数字。每个余数代表一个段。

此示例适用于MySQL(而不是Rails),用Postgress等效替换DIV(MySQL的整数除法函数)。

SELECT 
    AVG(heart_rate), HOUR(timestamp) DIV 4, COUNT(*)
FROM 
    vital_signs
GROUP BY 
    DATE(timestamp), 
    HOUR(timestamp) DIV 4;

您可以单独分组日期,因此每天都可获得平均值。结果

您可以通过以下方式直接在Rails中执行SQL:

ActiveRecord::Base.connection.execute "<sql>"

答案 1 :(得分:1)

模拟数学余数是一个很好的选择:

Model.count(group: 'CAST((24 - hour(table.created_at))/4 as UNSIGNED)')

它将为您提供一个散列,其中包含每组四小时的计数

{0=>2, 1=>1, 3=>1, 6=>2}

6代表0:00至4:00的开始,依此类推

您可以使用以下方法获得平均值:

Model.average(:field ,group: 'CAST((24 - hour(table.created_at))/4 as UNSIGNED)')

答案 2 :(得分:0)

尝试:

MyModel.select("(CASE 
  WHEN hour(created_at) < 4 then '00-04'
  WHEN hour(created_at) >= 4 and hour(created_at) < 8 then '04-08'
  WHEN hour(created_at) >= 8 and hour(created_at) < 12 then '08-12'
  WHEN hour(created_at) >= 12 and hour(created_at) < 16 then '12-16'
  WHEN hour(created_at) >= 16 and hour(created_at) < 20 then '16-20'
  ELSE '20-24' END) AS delta,
  count(*) as qty").
group("delta")

或者简单地说:

ActiveRecord::Base.connection.execute("SELECT (CASE 
  WHEN hour(created_at) < 4 then '00-04'
  WHEN hour(created_at) >= 4 and hour(created_at) < 8 then '04-08'
  WHEN hour(created_at) >= 8 and hour(created_at) < 12 then '08-12'
  WHEN hour(created_at) >= 12 and hour(created_at) < 16 then '12-16'
  WHEN hour(created_at) >= 16 and hour(created_at) < 20 then '16-20'
  ELSE '20-24' END) AS delta,
  count(*) as qty
  FROM  my_table
  group by delta;")

但我们的想法是让你的数据库引擎处理分组,而不是试图在ruby代码中做类似的事情。