How do I group by hour in Postgres & Rails? I've read through quite a few SO answers but I'm getting errors.
This works when grouping by date:
Model.group("date(updated_at)").count
Then I tried the following for hour but they didn't work:
Model.group("hour(updated_at)").count
Model.group("date_format(updated_at, '%H')").count
Model.group("extract(hour from updated_at)").count
Once I've found certain hours I need to update, how would I then get the models with those hours? I.e:
Model.where("hour(updated_at) = ?", 5)
You could try the following
Model.group("DATE_PART('hour', updated_at)").count
UPDATE:
How to find records
Model.where("DATE_PART('hour', updated_at) = ?", 5)
PostgreSQL presents two ways to extract a part of date/time:
EXTRACT is SQL standard function that exists in other SQL based databases.
Model.group("EXTRACT(hour FROM created_at)").count
Model.where("EXTRACT(hour FROM created_at) = ?", 5)
date_part function
Model.group("date_part('hour', updated_at)").count
Model.where("date_part('hour', updated_at) = ?", 5)
The official documentation.
If you want both the date and the hour, you can use date_trunc:
Model.group("date_trunc('hour', created_at)").count
And if you want the answers in order:
Model.order("date_trunc('hour', created_at)").group("date_trunc('hour', created_at)").count
Yeah it's weird that you can't just do order(:created_at) but oh well.
Related
In an attempt to summarise traffic data base on a time span, one cannot search invoking a component of a datetime object as such:
txat0 = Transaction.where(['shop_id = ? AND created_at.hour = ?', shop, 0]).count
One could go via the SQL route (i.e. postgresql)
select extract(shop_id, hour from created_at) from transactions
and filter from there.
But what is a succinct way of achieving this with ruby or rails (performance is not a concern for this query) ?
I believe you could do a mix and run the SQL part inside an ActiveRecord query.
What about:
Transaction.where("DATE_PART('hour', created_at) = ?", 0)
PS: I've ignored the shop_id clause in the above example, but you can just add it afterwards.
I want to get only those records of my model which belong to a particular month. I am using:
Order.where(created_at.strftime("%B"): "April")
where created_at is DateTime. created_at.strftime("%B") gives me month, but it does not work. Any alternative?
You'll probably have to do this in plan SQL (not the activerecord DSL):
Order.where("strftime('%m', created_at) = ?", 'April')
This uses the SQLite function to extract the month name
(I haven't done Rails in a while, let me know if this doesn't work)
I'm trying to figure out how to do a query where created_at.year == a given year, and created_at.month equals a given month.
However I can't figure out what I'm doing wrong.
Model.where("'created_at.month' = ? AND 'created_at.year' = ?", 7,2013)
results in nothing being shown.
However when I try Model.first.created_at.month ==7 and
Model.first.created_at.year ==2013 I get true for both.
Therefore theoretically my query should be at least be returning my first record.
Anyone know what I'm doing wrong or any alternative way to find records created on specific months?
Note that in my views the month / year will be parameters but for the purposes of this example I used actual values.
using ruby 1.9.3
rails 3.2.13
You can use the extract SQL function, that will extract the month and year of the timestamp:
Model.where('extract(year from created_at) = ? and extract(month from created_at) = ?', '2013','7')
This query should give you the desired result.
created_at is a timestamp; it is not a set of discrete fields in the database. created_at.year and such don't exist in your DB; it's simply a single timestamp field. When you call #model.created_at.year, Rails is loading the created_at field from the database, and creating a Time object from it, which has a #year method you can call.
What you want is to query on a range of dates:
Model.where("created_at >= ? and created_at < ?", Time.mktime(2013, 7), Time.mktime(2013, 8))
This will find any Model with a created_at timestamp in July 2013.
I have in my db a attribute where i save the record creation date.
The saved date has this format:
2013/06/18 19:03:24
I need to search only for date and i am not interested the time
I have try in this mode but it's doesn't work:
Report.find_all_by_created_at("2013-06-18").each do |r| %>
[...]
end
Given that created_at is a Rails generated column you can't really and just for created at date. Reason for that is in database created_at is saved as timestamp (or Datetime) so records created on 18th of June may have values from 2013-06-18 00:00:00 to 2013-06-18 23:59:59.
So, if you'd like to select all objects created on specific day you should do something like
Report.where('created_at >= ? AND created_at <= ?, Date.new(2013,6,18).beginning_of_day, Date.new(2013,6,18).end_of_day)
You can pass a range to where:
date = Date.new(2013,6,18)
Report.where(created_at: date.beginning_of_day..date.end_of_day)
This creates a SQL statement like:
SELECT `reports`.* FROM `reports` WHERE `reports`.`created_at` BETWEEN '2013-06-18 00:00:00' AND '2013-06-18 23:59:59'
Probably not the best solution but you could do:
Report.where("created_at >= ? and created_at < ?","2013-06-18","2013,06-19").each do |r|
[...]
end
It looks like you are collecting it as a DateTime and you would probably be able to use the to_date() method to change it to a Date object which would be searchable.
http://api.rubyonrails.org/classes/DateTime.html#method-i-to_date
you can use like matcher in sql query
Report.where("created_at LIKE '2013-06-18%'")
or look at the Squeel gem it can call SQL functions in ruby like syntax then you could use something thati will generate query with
WHERE cast(created_at as date) = '2013-06-18'
I am finding hard time figuring out a issue while trying to find records created this month.
my query in controller looks like this
#sh = SupportHistory.where('created_at BETWEEN ? AND ?', Time.now.beginning_of_month, DateTime.now.end_of_month)
my sql looks like this
SELECT `support_histories`.* FROM `support_histories` WHERE (created_at BETWEEN '2012-10-31 18:30:00' AND '2012-11-30 18:29:59')
The problem is its finding a record from previous month, how to fix it ?
Update
I was able to figure-out the problem through this link:
Timezone with rails 3
Now my query in controller looks like this
#sh = SupportHistory.where('created_at BETWEEN ? AND ?', DateTime.now.in_time_zone.beginning_of_month, DateTime.now.in_time_zone.end_of_month)
Now my sql looks like this
SELECT `support_histories`.* FROM `support_histories` WHERE (created_at BETWEEN '2012-11-01 05:
00:00' AND '2012-12-01 05:59:59')
Now i have another Question, is there a way to avoid 'in_time_zone' ? or to make it happen automatically ? :)