簡體   English   中英

活動記錄每日計數數組wrt created_at或Updated_at

[英]Active records daily count array w.r.t created_at or updated_at

我正在一個學校項目中,我有class_standard桌子class_standardenrollments

enrollments belongs_to的class_standardclass_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM