[英]Active records daily count array w.r.t created_at or updated_at
我正在一個學校項目中,我有class_standard
桌子class_standard
和enrollments
enrollments
belongs_to的class_standard
和class_standard
有許多enrollments
。
enrollments
在不同的日期。 我想獲取過去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
您要選擇按天分組的計數。 如何准確實現這一點取決於所使用的數據庫。
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}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.