查询忽略时间戳日期的时间范围
我正在尝试查询我的rails数据库(Postgres)中的购买表,我想查询时间范围。
例如,我想知道在所有日期的下午2点到下午3点之间进行了多少次购买。
此表中有一个created_at
列,但我没有看到如何在不搜索特定日期的情况下完成此操作。
我试过了:
Purchases.where("created_at BETWEEN ? and ?", Time.now - 1.hour, Time.now)
但这最终只会在那些时候搜索今天的日期。
您需要使用PostgreSQL的date_part / extract函数从created_at中提取小时部分。
http://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-EXTRACT
SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 20:38:40'); Result: 20
例如,像这样:
Purchases.where(["EXTRACT(HOUR FROM created_at) BETWEEN ? AND ?", 13, 14)
使用简单的演员time
:
Purchases.where("created_at ::time >= ? AND created_at ::time < ?", Time.now - 1.hour, Time.now)
这样您就可以轻松地对任意时间进行测试。
考虑:
-
包含/排除哪个边框。 通常的做法是包括下边界并排除鞋面。
BETWEEN
包括 ...... -
确切的数据类型(
timestamp with time zone
timestamp
或timestamp with time zone
)以及与当地时区的交互方式:
在Rails和PostgreSQL中完全忽略时区
指数
如果你经常运行这些查询并且需要它们快速而且表格不是很小,那么你需要为性能创建一个function索引 :
CREATE INDEX tbl_created_at_time_idx ON tbl (cast(created_at AS time));
注意:
-
我使用标准的SQL语法
cast()
而不是Postgres语法快捷方式::
。 这是指数所必需的。 -
此索引适用于
timestamp [without time zone]
因为IMMUTABLE
是索引所需的IMMUTABLE
。 但出于同样的原因,它不适用于timestamp with time zone
的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));
处理忽略年份的日期的类似问题:
你怎么做数学忽略年份?