Rails query data by hour - ruby-on-rails

I'm having difficulty querying data by an hour for the previous day. Using Rails 4 on Postgres.
eg,
Table X:
created_at, value
timestamp1 3
timestamp2 5
I want to get:
time, value
YYMMDD 00:00 15
YYMMDD 01:00 20
basically the sum per hour. I've tried
Rails & Postgresql: how to group queries by hour?
Is it possible to group by hour/minute/quarter hour directly in ActiveRecord/Rails?
but I still cant figure out how to get it to work properly, i get the wrong hour for replies. How would i set my timezone along with this query?
TableX.group("DATE_trunc('hour',created_at)").count
Thanks!

All you need is create a query like this one:
SELECT date_trunc('hours', created_at), sum(value)
FROM TableX
GROUP BY date_trunc('hours', created_at)
This one uses date_trunc instead of suggested date_part, which fits your question better.

Related

Ruby on Rails: How to get all the records and sort it by the lowest days difference of two dates

I am using postgresql. I have one table the Shipments table and I have two date columns on the table called arrival_date and release_date, what I wanted to do is to get all the record and sort it according to the lowest days difference of arrival_date and release_date, for example:
Arrival Date, Released Date
2017-06-04, 2017-06-30
2017-05-02, 2017-05-05
So in this example the days difference of first record is 26 days and the second one is 3 days, so the second record should be the first one.
The easiest way would be to subtract the two dates using Postgres:
ordered_shipments = Shipment.order("(arrival_date - released_date) ASC")
This will subtract the Unix timestamps of the two dates and sort the difference in ascending order.
I got inspiration from this answer.
I think that you need improve your query in postgres
in example
Table
id | dateA | dateB
select dateA, dateB, age(timestamp dateA, timestamp dateB) diffdate from Table order by diffdate desc;
You may want to use sort_by! method:
Shipment.all.sort_by!{ |shipment| shipment.released_date - shipment.arrival_date }

Average sales price for each day

I have Rails app with a PostgreSQL DB Sales Table that looks like this:
Sales
price(decimal) date(datetime)
100.20 11/25/2012 11:00:00
30.43 11/26/2012 03:00:00
124.43 11/25/2012 18:00:00
190.34 11/26/2012 22:00:00
The DB has thousands of records like this, spanning 10 years.
I need to find the average sales price for each day and save each as a separate record in another DB table via a rake task.
For further clarity, Sales need to be grouped by day (even though data is in datetime format), and then the price values for that day need to be averaged.
Since I have 10 years of days, the ability to loop through each daily group and perform the averages is essential.
Does anyone have any suggestions as to how to write this?
You'll need to double check the syntax, but something like this should do it all in the database...
Sales.average(:price, :group => "DATE_TRUNC('day', date)")
Note that DATE_TRUNC is PG specific.

Find all data that were created between 9 am and 4pm Rails 3.2.1 and postgreSQL

I have a requirement to display all data that were inserted in between 9 am and 5 pm ignoring dates.
I have tried
.where(created_at: Time.parse("9am")..Time.parse("5pm"))
*Because Time.parse results in current data and time. So this display only today's result between 9 am and 5 pm.But I need all the data that were entered in between 9am and 5pm *
I tried to solve using time data field in database. Database stores correctly but when we query through rails the year 01-01-2000 was appended in time.
Although it is a very simple problem, I am stuck.
Please help me to figure out this problem.
PostgreSQL defines a function EXTRACT described here: http://www.postgresql.org/docs/current/interactive/functions-datetime.html
You might be able to query using something like the following:
SELECT * FROM (modelname) WHERE EXTRACT(HOUR FROM created_at) > (minhour) AND EXTRACT(HOUR FROM created_at) < (maxhour);

rails - group by day as well as hour

I want to create an array of the number of items created each hour, each day.
I'm tracking how people are feeling, so my model is called TrackMood It just has a column called mood and the timestamps.
If I do
TrackMood.where(mood: "good").group("hour(created_at)").count
I get something like
{11=>4, 12=>2, 13=>2, 15=>1}
I've got 2 issues here
1 How do I add the day into this so it doesn't just add the items created yesterday at 11 o'clock to the items added today at 11 o'clock?
2 How do I make sure it says 0 for hours when nothing is created?
1) Instead of grouping on just the hours part of the date you'll need to group part of the date that is relevant i.e. the date up to the hours and not including anything more specific than that. E.g.
TrackMood.where(mood: "good").group("date_format(created_at, '%Y%m%d %H')").count
2) You're always going to get a hash back from this call even if it doesn't find any groups. If you want to check how many groups there are you can call .size or .count on it.
For PostgreSQL you can use date_part
SO-post - Rails & Postgresql: how to group queries by hour?

Rails: find by day of week with timestamp

I need to grab the records for same day of the week for the preceeding X days of the week. There must be a better way to do it than this:
Transaction.find_by_sql "select * from transactions where EXTRACT(DOW from date) = 1 and organisation_id = 4 order by date desc limit 7"
It gets me what I need but is Postgres specific and not very "Rails-y". Date is a timestamp.
Anyone got suggestions?
How many days do you want to go back?
I have written a gem called by_star that has a dynamic finder suited for finding up to a certain number of days in the past. If the number of days was always a number you could use this finder:
Transaction.as_of_3_days_ago
If it was dynamic then I would recommend using something such as future or between, depending on if you have transactions in the future (i.e. time travel):
Transaction.future(params[:start_date].to_time)
Transaction.between(params[:start_date].to_time, Time.now)
AFAIK Rails has no any methods to do this by other way. So best, and faster, solution - build DOW index on date column and use your query.

Resources