根据 Rails Active Record 中时间戳/日期时间的时间部分从 PostgreSQL 中提取记录

问题描述 投票:0回答:1

我正在 Rails 应用程序中使用 PostgreSQL 数据库,并面临着仅根据用户表中的

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:00
12:30
之间创建的所有用户。

我也尝试过这个:

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

但它只处理小时而不是分钟。

所需时间可以是

10
-
12
小时或
10:00
-
12:30
。 如果我想提取从
10:00
12:30
的记录,我该如何管理这些分钟?

简而言之,我正在寻找可以指定所需时间并获取这些时间段内的所有记录的方法。

sql ruby-on-rails postgresql rails-activerecord
1个回答
1
投票

PostgreSQL 有一种

time
类型,您可以将
timestamp
转换为该类型,以便一次性提取几小时内的所有内容(不排除秒和秒的分数)。 db<>fiddle 的演示:

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);
select created_at
from test
where created_at::time between '11:15' and '12:21:10.123';
创建于
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,您可以将时间字段传递到 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 上添加

功能索引
来进一步加快速度:

create index on test((created_at::time));
© www.soinside.com 2019 - 2024. All rights reserved.