Reputation: 1098
In SQL, I'd use something like this:
SELECT year(created_at)
FROM videos
GROUP BY year(created_at)
How can I run this query with Rails?
I've tried this:
Video.all.group_by { |m| m.created_at.year }
... but this will return ALL my records grouped by the corresponding years, which is not entirely bad, except it's returning hundreds of records, when I only need to know the years.
Any pointers?
In case you're wondering I'm using Rails 5.1.5 and MariaDB (10.2.14-MariaDB-10.2.14+maria~xenial-log).
Upvotes: 0
Views: 2064
Reputation: 139
If you want only years from data you can do
videos = Video.group("created_at").select("videos.created_at")
it will fetch only created_at
column
and you can access year from created_at column by
videos.first.created_at.year
Upvotes: 0
Reputation: 649
I'm using
Event.group("strftime('%Y', created_at)")
For example:
Event.group("strftime('%Y', created_at)").count
has the output:
{"2019"=>456}
You can even group by a child's created_at
this way:
Application.group("strftime('%Y', events.created_at)")
This would require, that an applications
has many events
in my particular case.
Upvotes: 0
Reputation: 230346
Not everything can be expressed in activerecord-speak without losing efficiency here or there. Or some things can't be expressed at all. That's why you can run arbitrary SQL:
Video.connection.execute("select year(created_at)....")
Having actually read your SQL, you want distinct years of the records? So, perhaps this? Should be even faster (benchmarking needed).
SELECT DISTINCT YEAR(created_at) FROM videos
Upvotes: 1
Reputation: 230346
Turns out, pluck
accepts expressions, not only column names. So you can do this for max efficiency (at the cost of portability).
Video.distinct.pluck("year(created_at)") # mysql
Video.distinct.pluck("extract(year from created_at)") # postgresql
Same efficiency as running raw sql (from my other answer), but looks a bit more ActiveRecord-y.
If you want a portable solution, then I can't think of anything better than Mark's answer.
Upvotes: 3
Reputation: 2398
You can also do:
Video.all.map {|u| u.created_at.year}
This would return a array containing the years in which each Video
was created.
Upvotes: 0
Reputation: 2695
You could do something like this to get an array of unique years...
Video.pluck(:created_at).map{ |dt| dt.year }.uniq
Upvotes: 3