按周/月/等和 ActiveRecord 分组?

Posted

技术标签:

【中文标题】按周/月/等和 ActiveRecord 分组?【英文标题】:Grouping by week/month/etc & ActiveRecord? 【发布时间】:2010-10-28 12:39:35 【问题描述】:

我正在我的产品中进行一些静态计算。用户执行了许多操作,比如说发布的 cmets。我希望能够向他们展示他们在过去一个月中每周发布了多少 cmets,或者在过去一年中每月发布了多少 cmets。

activerecord 有什么办法可以这样分组吗?我最好的办法是简单地手动执行此操作 - 根据我自己的标准迭代记录总和吗?

class User < ActiveRecord::Base
  has_many :comments
end

class Comments < ActiveRecord::Base
  belongs_to :user
end

@user.comments(:all).map |c| ...do my calculations here...

或者有更好的方法吗?

谢谢! 奥伦

【问题讨论】:

【参考方案1】:

在这种情况下,对我来说最好的解决方案是直接使用 SQL,或者使用 Ruby group_by 函数:

@user.all.group_by |u| u.created_at.beginning_of_month 

【讨论】:

group_by 不是 ActiveRecord 方法,而是Enumerable 上的 Ruby 方法。 只使用u.created_at.month会更短 请注意,这会从数据库中加载所有记录,实例化 ActiveRecord 对象,将日期解析为 ActiveSupport 的时区感知对象——所有这些都只是为了计算记录数。 这是一种不好的做法,因为当您使用 .all 时,它会获取数据库中的所有记录,这将花费您太多 多么浪费内存!使用@WojtekKruszewski 解决方案:@user.comments.group("DATE_TRUNC('month', created_at)").count【参考方案2】:

查看团体日期宝石

https://github.com/ankane/groupdate

它具有最近的提交,与 postgresql 一起使用,与 chart kick 轻松集成以实现快速图表,并且与时区一起使用!!

【讨论】:

GroupDate 仅适用于 UTC,因此如果您在数据库中使用其他时区,请考虑替代方案。【参考方案3】:

使用 group_by

@user.comments.group_by(&:week)

class User < ActiveRecord::Base
  def week
    some_attribute_like_date.strftime('%Y-%W')
  end
end

这将为您提供格式为 YYYY-WW 的分组列表

【讨论】:

【参考方案4】:

这是更精致的版本

@user.comments.group("year(created_at)").group("month(created_at)").count

【讨论】:

【参考方案5】:

我的猜测是这样的:

@user.comments.count(:group => "year(created_at),month(created_at)")

干码,ymmv

【讨论】:

我相信这也会按月分组 - 所以如果你有两年的数据,所有的东西都在第 1 年和第 2 年 1 月。我正在寻找的是一种方法例如,告诉一个 24 个月的窗口,每月有多少。 您也可以添加一个条件来限制年份,例如 :conditions => [:created_at, "> #24.months.ago"]。同样,未经测试,但应该可以使用这样的东西。 这似乎是 mysql 特有的【参考方案6】:

在 Postgres 中你可以这样做:

@user.comments.group("DATE_TRUNC('month', created_at)").count

得到:

"2012-08-01 00:00:00"=>152, "2012-07-01 00:00:00"=>57, "2012-09-01 00:00:00"=>132

它接受从“微秒”到“千年”的值进行分组: http://www.postgresql.org/docs/8.1/static/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC

【讨论】:

比使用 ruby​​ 可枚举 group_by 快得多! Wojtek,如果一个月内什么都没有创建呢?那个月你什么也得不到。 @MattSmith 我相信是的。幸运的是,从该查询的输出中读取值时提供默认值很容易:output.fetch("2012-08-01 00:00:00", 0) 在我的例子中,键是 Ruby Time 对象,所以我可以使用result[Time.current.utc.beginning_of_month] 访问结果。不知道为什么答案会显示带有字符串键的结果,或者多年来是否发生了变化。 有排序吗?哈哈,钥匙坏了【参考方案7】:

查看 has_activity 插件。

【讨论】:

感谢您的指点。看起来 has_activity 只是 mysql 。我的生产主机是 postgresql。

以上是关于按周/月/等和 ActiveRecord 分组?的主要内容,如果未能解决你的问题,请参考以下文章

MySql按周,按月,按日分组统计数据

Oracle里面如何让一段日期按周、月、季度、年分组显示啊?求高手赐教,贴出正确sql追加高分!

使用 concat 按周分组 SQL

SQL Server 按过去 24 小时、上周和上个月对促销进行分组,并按周降序排序

在mysql中计算数据并按周分组

SQL 分组按周和月在同一时间 (Redshift)