[英]Active records daily count array w.r.t created_at or updated_at
I am working on a school project where I have tables class_standard
and enrollments
我正在一个学校项目中,我有
class_standard
桌子class_standard
和enrollments
enrollments
belongs_to class_standard
and class_standard
has many enrollments
. enrollments
belongs_to的class_standard
和class_standard
有许多enrollments
。
enrollments
are created_at in different days. enrollments
在不同的日期。 I want to get daily counts of enrollments in last 30 days in an array. 我想获取过去30天内阵列中的每日报名人数。
ie [# of enrollments 1st day, 2nd day, 3rd day, .....] 例如[第1天,第2天,第3天,.....的注册人数]
This is the sample of the code that gets the daily count of Enrollments created and stores them in an array. 这是代码示例,该代码获取创建的每日注册计数并将其存储在数组中。
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
What you want to do is select a count grouped by day. 您要选择按天分组的计数。 How exactly to achieve this depends on what database is used.
如何准确实现这一点取决于所使用的数据库。
Postgres: Postgres:
date_trunc('day', created_at)
MySQL: MySQL:
date_format(created_at, '%Y-%m-%d')
For other db's check the documentation for date functions. 对于其他数据库,请查阅有关日期函数的文档。
Altogether the query you want is something like this: 总共您想要的查询是这样的:
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
We can write this in ActiveRecord as: 我们可以在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))
But this gives an ActiveRecord::Relation of records which is not very useful. 但这给出了一个ActiveRecord :: Relation记录,这不是很有用。 To get the raw query values we want to use
#select_all
. 要获取原始查询值,我们要使用
#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)
When you convert the results to an array you will get an array of hashes: 将结果转换为数组时,将获得一个哈希数组:
[{"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"}, ...]
You can extract the count by mapping the array: 您可以通过映射数组来提取计数:
results.map {|r| r["count"] }
If you want the results just for one (or more) ClassStandards just add an additional condition to the where clause: 如果只需要一个(或多个)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
Or you call it off the association: 或者您将其取消关联:
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
If you want to get count of all days including the days where there isn't any enrollment: 如果您想计算所有天数,包括没有注册的天数:
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
Output Example 输出范例
[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]
This will give you an array of all 30 days. 这将为您提供所有30天的阵列。 But this isn't seems an efficient code.
但这似乎不是有效的代码。 This will run 30 queries for each record.
每个记录将运行30个查询。
What seems better to me is group the records on created_at
and get records for the days which have some records. 对我来说似乎更好的是将记录分组在
created_at
并获取具有某些记录的日期的记录。 ie excluding days with no record. 即排除没有记录的天数。
Enrollments.where(created_at: Time.current - 30.days..Time.current)
.group("date(created_at)")
.count
.sort
.to_h
Output Example 输出范例
{Mon, 19 Nov 2018=>12}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.