5

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

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

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

我试过了:

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

但这最终只会与那些时代一起寻找今天的日期。

4

2 回答 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])
于 2013-10-14T20:02:04.053 回答
4

使用简单的演员表time

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

这样您就可以轻松地针对任意时间进行测试。

考虑:

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

  • 确切的数据类型(timestamptimestamp with time zone)以及它如何与您的本地时区交互:

指数

如果您经常运行这些查询并且需要它们快速并且您的表不是很小,您将需要创建一个功能索引以提高性能:

CREATE INDEX tbl_created_at_time_idx ON tbl (cast(created_at AS time));

我使用标准 SQL 语法cast()而不是 Postgres 语法快捷方式::。这是索引所必需的。

该索引适用于 a,timestamp [without time zone]因为强制转换是IMMUTABLE索引所需的。timestamp with time zone但出于同样的原因,它不适用于 a 。您可以解决此问题,但您需要准确定义您需要的内容。使用AT TIME ZONE构造来定义时区以提取时间。例如,要根据 UTC 时间进行测量:

CREATE INDEX tbl_created_at_time_idx2
ON tbl(cast(created_at AT TIME ZONE 'UTC' AS time));

处理忽略年份的日期的类似问题:

于 2013-10-14T20:45:58.770 回答