基于Rails Active Record中的timestamp/DateTime组件从PostgreSQL中提取记录

r7xajy2e  于 11个月前  发布在  PostgreSQL
关注(0)|答案(1)|浏览(196)

我在一个rails应用程序中使用PostgreSQL数据库,面临着一个挑战,那就是只根据users表中timestamp类型created_at列的时间组件来提取用户记录。
此查询工作正常:

users = User.where("    DATE_PART('hour',   created_at) >= ? 
                    AND DATE_PART('minute', created_at) >= ? 
                    OR  DATE_PART('hour',   created_at) <= ? 
                    AND DATE_PART('minute', created_at) <= ?", 
                    10, 0, 15, 30).pluck :created_at

字符串
但我很好奇是否有更优雅的方法来提取所需的记录。本质上,我的目标是仅基于时间查询记录,不包括日期。例如,我想检索在10:0012:30之间创建的任何一天的所有用户(年,月和日无关)。
我也试过这个:

User.where("EXTRACT(HOUR FROM created_at) BETWEEN ? AND ?", 14, 15)


但它只处理小时而不是分钟。
所需的时间可以是10-12小时或10:00-12:30。如果我想提取10:0012:30的记录,如何管理这些分钟?
简而言之,我正在寻找一种方法,可以指定所需的时间并获得这些时间段内的所有记录。

rn0zuynd

rn0zuynd1#

PostgreSQL有一个time类型,你可以将timestamp转换为它,以便一次性提取从小时开始的所有内容(不包括秒和秒的分数)。

create table test(created_at timestamp);

--sample timestamps around every hour between now and 4 days from now
insert into test select g+random()*'1h'::interval 
from generate_series(now(),now()+'4 days','1h')_(g);

个字符
| 创建于|
| --|
| 2023-12-08 11:55:58.167576|
| 2023-12-09 11:39:04.189425|
| 2023-12-10 12:09:11.234004|
| 2023-12-11 11:40:42.80833|
在RoR中,你可以将time字段传入PostgreSQL make_time()。第三个字段是double precision,它允许你用分数传递秒:

User.where("created_at::time BETWEEN make_time(?,?,?) 
                             AND     make_time(?,?,?)", 
           11, 15, 0, 
           12, 21, 10.123)


您也可以传递任何具有匹配时间的时间戳,并强制转换为仅使用其time元素:

User.where("created_at::time BETWEEN cast(:start_time as time) 
                             AND     cast(:end_time   as time)", 
           {start_time: Time.new(2023,12,07,11,15), 
            end_time: DateTime.new(1981,05,05,15,30)} )


可以通过在created_at上添加functional index来进一步加快速度:

create index on test((created_at::time));

相关问题