您如何使用ActiveRecord从“ created_at”中按年份分组?

时间:2018-07-27 08:49:50

标签: ruby-on-rails ruby-on-rails-5 mysql2

在SQL中,我会使用类似这样的内容:

SELECT year(created_at)
FROM videos
GROUP BY year(created_at)

如何使用Rails运行此查询?

我已经尝试过了:

Video.all.group_by { |m| m.created_at.year }

...但是这将返回我所有按相应年份分组的记录,这并不完全不好,只是当我只需要知道年份时它返回数百条记录。

有指针吗?

如果您想知道我使用的是Rails 5.1.5和MariaDB(10.2.14-MariaDB-10.2.14 + maria〜xenial-log)。

6 个答案:

答案 0 :(得分:3)

您可以执行以下操作来获得一系列独特的年份...

Video.pluck(:created_at).map{ |dt| dt.year }.uniq

答案 1 :(得分:1)

并非所有内容都可以在ActiveRecord讲话中表达,而不会在这里或那里失去效率。或有些事情根本无法表达。这就是为什么您可以运行任意SQL的原因:

Video.connection.execute("select year(created_at)....")

实际上已经阅读了您的SQL,您想要不同的记录年份吗?那么,也许这呢?应该更快(需要基准测试)。

SELECT DISTINCT YEAR(created_at)  FROM videos

答案 2 :(得分:1)

结果是,pluck接受表达式,不仅接受列名。因此,您可以这样做以获得最大效率(以可移植性为代价)。

Video.distinct.pluck("year(created_at)") # mysql
Video.distinct.pluck("extract(year from created_at)") # postgresql

与运行原始sql的效率相同(从我的其他答案中得出),但看起来有点ActiveRecord-y。

如果您想要一个便携式解决方案,那么我想不出比Mark's answer更好的了。

答案 3 :(得分:0)

如果您只希望从数据中提取年份,则可以这样做

videos = Video.group("created_at").select("videos.created_at")

它将仅获取created_at列

您可以通过created_at列中的年份访问

videos.first.created_at.year

答案 4 :(得分:0)

您也可以这样做:

Video.all.map {|u| u.created_at.year}

这将返回一个数组,其中包含每个Video的创建年份。

答案 5 :(得分:0)

我正在使用

Event.group("strftime('%Y', created_at)")

例如:

Event.group("strftime('%Y', created_at)").count

具有输出:

{"2019"=>456}

您甚至可以通过以下方式对孩子的created_at进行分组:

Application.group("strftime('%Y', events.created_at)")

在我的特殊情况下,这需要一个applications有很多events