Reputation: 8570
Rails 3 app, pg adapter, my schema look as:
create_table "events", :force => true do |t|
t.integer "event_type_id"
t.datetime "start_at"
#...
end
Some example data include:
p.events.each{|e| puts e.start_at }; 1
2009-03-23 08:30:00 UTC
2009-05-20 07:45:00 UTC
2009-05-20 07:45:00 UTC
2009-03-23 16:00:00 UTC
2009-05-20 10:00:00 UTC
2009-03-23 19:30:00 UTC
2009-03-23 11:30:00 UTC
2009-05-20 07:45:00 UTC
2009-05-20 07:45:00 UTC
2009-05-20 09:00:00 UTC
2009-05-20 07:45:00 UTC
I'd like to search in between the next 3 hours, but ignoring the day! Hour and minute is all that matters to me..
Is it possible to be done in Postgres? I've been trying to use pg EXTRACT(), but no success so far
I don't want to filter all dates in ruby code :(
Upvotes: 0
Views: 520
Reputation: 8570
Ignoring the minutes, and only taking into account the hours:
#On my model
scope :next_3_hours, ->(h){
where( [" date_part( 'hour', \"start_at\") = ? OR date_part( 'hour', \"start_at\") = ? OR date_part( 'hour', \"start_at\") = ? ",h,h+1,h+2])
.order("date_part( 'hour', \"start_at\") ASC, date_part( 'minute', \"start_at\")")
}
result:
# on SQL (considering now to be 17:00)
SELECT "events".* FROM "events"
WHERE ( date_part( 'hour', "start_at") = 17
OR date_part( 'hour', "start_at") = 18
OR date_part( 'hour', "start_at") = 19 )
ORDER BY date_part( 'hour', "start_at") ASC, date_part( 'minute', "start_at")
Upvotes: 1
Reputation: 10648
I introduce only one way how this can be done in PostgreSQL. I've no RoR experience so I can't help you on that part.
The basic idea below is that all timestamps are converted to the same day so the hours and minutes can be compared:
create table test (id serial, start_at timestamp);
insert into test(start_at)
select * from generate_series('2008-03-01 00:00'::timestamp,
'2008-03-15 12:00', '5 hours');
with
hh24mi_now as (select to_timestamp(to_char(current_timestamp, 'HH24:MI'), 'HH24:MI'))
select * from test where id in (
select id
from test
where to_timestamp(to_char(start_at, 'HH24:MI'), 'HH24:MI') >= (select * from hh24mi_now)
and to_timestamp(to_char(start_at, 'HH24:MI'), 'HH24:MI') < (select * from hh24mi_now) + interval '3 hours'
)
order by id
;
Result of an example run:
id | start_at
----+---------------------
13 | 2008-03-03 12:00:00
18 | 2008-03-04 13:00:00
23 | 2008-03-05 14:00:00
37 | 2008-03-08 12:00:00
42 | 2008-03-09 13:00:00
47 | 2008-03-10 14:00:00
61 | 2008-03-13 12:00:00
66 | 2008-03-14 13:00:00
Upvotes: 1