Активные записи суточного массива подсчетов - PullRequest
0 голосов
/ 19 ноября 2018

Я работаю над школьным проектом, в котором у меня есть таблицы class_standard и enrollments

enrollments принадлежит_ * class_standard, а class_standard имеет много enrollments.

enrollments созданы_ в разные дни.Я хочу получать ежедневные подсчеты зачислений за последние 30 дней в массиве.

т.е. [число зачислений 1-й день, 2-й день, 3-й день, .....]

Ответы [ 3 ]

0 голосов
/ 19 ноября 2018

То, что вы хотите сделать, это выбрать счетчик, сгруппированный по дням. Как именно этого добиться, зависит от того, какая база данных используется.

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 of records, что не очень полезно. Чтобы получить необработанные значения запроса, мы хотим использовать #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
0 голосов
/ 19 ноября 2018

Если вы хотите получить количество всех дней, включая дни, в которые не было зарегистрировано:

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}
0 голосов
/ 19 ноября 2018

Это пример кода, который получает дневной счет созданных заявок и сохраняет их в массиве.

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
...