忽略时间戳日期的时间范围查询

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

我正在尝试查询我的 Rails 数据库 (Postgres) 中的购买表,并且我想查询时间范围。

例如,我想知道所有日期的下午 2 点到下午 3 点之间进行了多少次购买。

此表中有一个

created_at
列,但我不知道如何在不搜索特定日期的情况下完成此操作。

我已经尝试过:

Purchases.where("created_at BETWEEN ? and ?", Time.now - 1.hour, Time.now)

但这最终只会搜索今天的日期和那些时间。

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

您需要使用 PostgreSQL 的 date_part/extract 函数从created_at 中提取小时部分。

SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 20

例如,像这样:

Purchases.where(["EXTRACT(HOUR FROM created_at) BETWEEN ? AND ?", 13, 14])

4
投票

使用简单的转换来

time
:

Purchases.where("created_at::time >= ?
             AND created_at::time <  ?", Time.now - 1.hour, Time.now)

这样您就可以轻松地测试任意时间

考虑:

  • 要包含/排除哪个边框。常见的做法是“包含”下边框并“排除”上边框。 BETWEEN 包括两者。

    
    确切的数据类型(

    timestamp
  • timestamp with time zone

    )以及它如何与您当地的时区交互:

    
    

    忽略 Postgres 时间戳的时区
  • 索引

  • 如果您经常运行这些查询并且需要快速运行并且您的表不是很小,您将需要创建一个

功能索引

以提高性能: CREATE INDEX tbl_created_at_time_idx ON tbl (cast(created_at AS time)); 我使用了

标准 SQL 语法
cast()
而不是 Postgres 语法快捷方式

::

。这是索引所必需的。
此索引适用于 
timestamp [without time zone]

,因为根据索引的要求,演员阵容是 IMMUTABLE

。但出于同样的原因,它不适用于 
timestamp with time zone
。您可以解决此问题,但您需要准确定义您需要的内容。使用 
AT TIME ZONE
构造来定义要提取时间的时区。例如,要根据 UTC 时间进行测量:
CREATE INDEX tbl_created_at_time_idx2
ON tbl(cast(created_at AT TIME ZONE 'UTC' AS time));
处理忽略年份的日期的类似问题:

如何进行忽略年份的日期数学?

© www.soinside.com 2019 - 2024. All rights reserved.