【问题标题】:With Rails, how can I query the db for an aggregate number and grouped by week?使用 Rails,我如何查询数据库以获取聚合数并按周分组?
【发布时间】:2017-11-23 06:37:15
【问题描述】:

给定这样的表格:

日志:

id, user_id, points, created_at

使用 Rails,我如何通过 user_id 查询数据库,然后通过 created_at 按周分组,然后我可以得到类似的东西:

   WEEK of X/XX/XXXX - 3011 total points
   WEEK of X/XX/XXXX - 320 total points
   WEEK of X/XX/XXXX - 31 total points
   WEEK of X/XX/XXXX - 30330 total points

谢谢

【问题讨论】:

  • 如果你使用的是 postgresql,你可以这样做:User.all.group("DATE_TRUNC('week', created_at)"). 但这只会让你走到一半。
  • 您使用的是什么数据库?
  • Log.sum(:points).group("DATE_TRUNC('week', created_at)").where(user_id: user_id) 应该为postgres 做这件事。如果您使用的是另一个数据库,则必须确定如何将分组处理为几周。
  • 我正在使用 postgres

标签: ruby-on-rails ruby postgresql activerecord ruby-on-rails-5


【解决方案1】:
points_by_week = Log.where(user_id: user_id).group("DATE_TRUNC('year', created_at)", "DATE_TRUNC('week', created_at)").sum(:points)

会产生类似的结果

{[2014, 4]=>3,
 [2014, 8]=>7,
 [2015, 4]=>26,
 [2015, 6]=>19,
 [2015, 12]=>50,
 [2015, 32]=>48,
 [2016, 2]=>78,
 [2016, 3]=>45,
 [2016, 4]=>49,
 [2016, 5]=>110,
 [2016, 45]=>30,
 [2017, 4]=>130,
 [2017, 11]=>185}

其中key是[year, week],那么可以使用Date.commercial获取星期

points_by_week.each do |(year, week), count|
  date = Date.commercial(year, week)
  puts "Week of #{date.strftime('%d/%m/%Y')} - #{count} total points"
end

而且(只是因为我可以),查询的 mysql 版本看起来像这样

points_by_week = Log.where(user_id: user_id).group("year(created_at)", "week(created_at)").sum(:points)

默认情况下,假设一周从星期一开始,一年的第一周从一年中的第一个星期一开始

【讨论】:

  • 这太好了 - 谢谢!仅供参考,由于DATE_TRUNC('week' 后缺少逗号而导致错误
【解决方案2】:

类似:

points_by_week = Log.select("DATE_TRUNC('week', created_at) as week, sum(points) as total_points").group("week").where(user_id: x)

points_by_week.each do |pw|
  puts "Week of #{pw.week.strftime('%d/%m/%Y')} - #{pw.total_points} total points"
end

编辑

根据 Michael Gorman 的评论,上面不会区分年份(2017 年、2016 年等),因此您可能需要根据您的要求按周和年分组:

Log.select("DATE_TRUNC('week', created_at) as week, DATE_TRUNC('year', created_at) as year, sum(points) as total_points").group("week, year")

你可以继续使用上面的循环来显示它;)

【讨论】:

  • 此查询不会区分 2016 年第 1 周和 2017 年第 1 周
【解决方案3】:

类似这样的:

select 'WEEK of ' || TO_CHAR(date_trunc( 'week', created_at ), 'dd/mm/yyyy') || ' - ' || sum(points) || ' total points'
FROM clients
  WHERE id < 100000
  GROUP BY date_trunc( 'week', created_at );

|| 用于连接字符串。

TO_CHAR用作数据类型格式化函数。

【讨论】:

    猜你喜欢
    • 2020-02-05
    • 2019-05-19
    • 2017-03-06
    • 2017-03-26
    • 1970-01-01
    • 2020-12-07
    • 2011-07-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多