Rails在小时和分钟之间进行AR查询



Rails 3应用程序,pg适配器,我的模式看起来是:

create_table "events", :force => true do |t|
 t.integer  "event_type_id"
 t.datetime "start_at"
 #...
end

一些示例数据包括:

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

我想在接下来的3个小时内搜索,但忽略当天小时和分钟对我来说才是最重要的。
有可能在Postgres中完成吗?我一直在尝试使用pg EXTRACT(),但到目前为止没有成功

我不想过滤ruby代码中的所有日期:(

我只介绍一种在PostgreSQL中实现这一点的方法。我没有RoR的经验,所以在这方面我帮不了你。

下面的基本思想是,所有时间戳都转换为同一天,因此可以比较小时和分钟:

  1. 将时间戳转换为仅包括小时和分钟的字符串
  2. 将该字符串转换回时间戳会导致日期部分为第1年的1月1日

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
;

示例运行的结果:

 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

忽略分钟,只考虑小时:

#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")")
}

结果:

# 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")

最新更新