活动记录每日计数数组 w.r.t created_at 或 updated_at
Active records daily count array w.r.t created_at or updated_at
我正在做一个学校项目,我有表 class_standard
和 enrollments
enrollments
belongs_to class_standard
和 class_standard
有很多 enrollments
.
enrollments
是 created_at 在不同的日子。我想获取数组中过去 30 天的每日注册人数。
即[第 1 天、第 2 天、第 3 天的注册人数......]
这是获取每天创建的注册人数并将其存储在数组中的代码示例。
arr = [] #initialize an array
(0..29).each do |x| #run a loop for 30 days
date = Time.now - x.days #get a specific day
arr << Enrollment.where(created_at: date.midnight..date.end_of_day).count #get count of enrollments on a specific day and add this to your array
end
arr = arr.reverse #reverse the array, because you want the today's count as last item of the array
您想要做的是 select 按天分组的计数。具体如何实现取决于所使用的数据库。
Postgres:
date_trunc('day', created_at)
MySQL:
date_format(created_at, '%Y-%m-%d')
对于其他数据库,请查看日期函数的文档。
总的来说你想要的查询是这样的:
SELECT
count(*) AS count,
date_trunc('day', created_at) AS day
FROM "enrollments"
WHERE (created_at >= ?) -- one month ago
GROUP BY day
ORDER BY day
我们可以在 ActiveRecord 中这样写:
Enrollment.select("count(*) AS count, to_char(created_at, 'YYYY-MM-DD') AS day")
.group("day")
.order("day")
.where(created_at: (1.month.ago..Time.current))
但这给出了 ActiveRecord::Relation 的记录,这不是很有用。要获取原始查询值,我们要使用 #select_all
.
sql = Enrollment.select("count(*) AS count, date_trunc('day', created_at) AS day")
.group("day")
.order("day")
.where("created_at >= ?", 1.month.ago)
.to_sql
results = Enrollment.connection.select_all(sql)
当您将结果转换为数组时,您将得到一个哈希数组:
[{"count"=>10, "day"=>"2018-10-20 00:00:00"}, {"count"=>10, "day"=>"2018-10-21 00:00:00"}, {"count"=>10, "day"=>"2018-10-22 00:00:00"}, {"count"=>10, "day"=>"2018-10-23 00:00:00"}, {"count"=>10, "day"=>"2018-10-24 00:00:00"}, {"count"=>10, "day"=>"2018-10-25 00:00:00"}, ...]
您可以通过映射数组来提取计数:
results.map {|r| r["count"] }
如果您只想获得一个(或多个)ClassStandards 的结果,只需在 where 子句中添加一个附加条件:
sql = Enrollment.select("count(*) AS count, date_trunc('day', created_at) AS day")
.group("day")
.order("day")
.where("created_at >= ?", 1.month.ago)
.where(class_standard: @class_standard)
.to_sql
或者你取消关联:
sql = @class_standard.enrollments
.select("count(*) AS count, date_trunc('day', created_at) AS day")
.group("day")
.order("day")
.where("created_at >= ?", 1.month.ago)
.to_sql
如果您想计算所有天数,包括没有任何注册的天数:
daily_enrollments = []
i = 29
while i >= 0
daily_enrollments >> Enrollments.where( created_at: Time.zone
.now
.beginning_of_day-i.day..
Time.zone
.now
.end_of_day-i.day).count
i = i-1
end
输出示例
[0,0,0,5,4,0,0,0,5,0,23,0,0,23,0,0,1,0,11,0,21,32,44,0,0,9,6,3,22,1]
这将为您提供所有 30 天的数组。但这似乎不是有效的代码。这将为每条记录 运行 30 个查询。
对我来说更好的方法是将 created_at
上的记录分组,并获取有一些记录的日子的记录。即排除没有记录的天数。
Enrollments.where(created_at: Time.current - 30.days..Time.current)
.group("date(created_at)")
.count
.sort
.to_h
输出示例
{Mon, 19 Nov 2018=>12}
我正在做一个学校项目,我有表 class_standard
和 enrollments
enrollments
belongs_to class_standard
和 class_standard
有很多 enrollments
.
enrollments
是 created_at 在不同的日子。我想获取数组中过去 30 天的每日注册人数。
即[第 1 天、第 2 天、第 3 天的注册人数......]
这是获取每天创建的注册人数并将其存储在数组中的代码示例。
arr = [] #initialize an array
(0..29).each do |x| #run a loop for 30 days
date = Time.now - x.days #get a specific day
arr << Enrollment.where(created_at: date.midnight..date.end_of_day).count #get count of enrollments on a specific day and add this to your array
end
arr = arr.reverse #reverse the array, because you want the today's count as last item of the array
您想要做的是 select 按天分组的计数。具体如何实现取决于所使用的数据库。
Postgres:
date_trunc('day', created_at)
MySQL:
date_format(created_at, '%Y-%m-%d')
对于其他数据库,请查看日期函数的文档。
总的来说你想要的查询是这样的:
SELECT
count(*) AS count,
date_trunc('day', created_at) AS day
FROM "enrollments"
WHERE (created_at >= ?) -- one month ago
GROUP BY day
ORDER BY day
我们可以在 ActiveRecord 中这样写:
Enrollment.select("count(*) AS count, to_char(created_at, 'YYYY-MM-DD') AS day")
.group("day")
.order("day")
.where(created_at: (1.month.ago..Time.current))
但这给出了 ActiveRecord::Relation 的记录,这不是很有用。要获取原始查询值,我们要使用 #select_all
.
sql = Enrollment.select("count(*) AS count, date_trunc('day', created_at) AS day")
.group("day")
.order("day")
.where("created_at >= ?", 1.month.ago)
.to_sql
results = Enrollment.connection.select_all(sql)
当您将结果转换为数组时,您将得到一个哈希数组:
[{"count"=>10, "day"=>"2018-10-20 00:00:00"}, {"count"=>10, "day"=>"2018-10-21 00:00:00"}, {"count"=>10, "day"=>"2018-10-22 00:00:00"}, {"count"=>10, "day"=>"2018-10-23 00:00:00"}, {"count"=>10, "day"=>"2018-10-24 00:00:00"}, {"count"=>10, "day"=>"2018-10-25 00:00:00"}, ...]
您可以通过映射数组来提取计数:
results.map {|r| r["count"] }
如果您只想获得一个(或多个)ClassStandards 的结果,只需在 where 子句中添加一个附加条件:
sql = Enrollment.select("count(*) AS count, date_trunc('day', created_at) AS day")
.group("day")
.order("day")
.where("created_at >= ?", 1.month.ago)
.where(class_standard: @class_standard)
.to_sql
或者你取消关联:
sql = @class_standard.enrollments
.select("count(*) AS count, date_trunc('day', created_at) AS day")
.group("day")
.order("day")
.where("created_at >= ?", 1.month.ago)
.to_sql
如果您想计算所有天数,包括没有任何注册的天数:
daily_enrollments = []
i = 29
while i >= 0
daily_enrollments >> Enrollments.where( created_at: Time.zone
.now
.beginning_of_day-i.day..
Time.zone
.now
.end_of_day-i.day).count
i = i-1
end
输出示例
[0,0,0,5,4,0,0,0,5,0,23,0,0,23,0,0,1,0,11,0,21,32,44,0,0,9,6,3,22,1]
这将为您提供所有 30 天的数组。但这似乎不是有效的代码。这将为每条记录 运行 30 个查询。
对我来说更好的方法是将 created_at
上的记录分组,并获取有一些记录的日子的记录。即排除没有记录的天数。
Enrollments.where(created_at: Time.current - 30.days..Time.current)
.group("date(created_at)")
.count
.sort
.to_h
输出示例
{Mon, 19 Nov 2018=>12}