从时间戳列中选择日期范围

时间:2011-09-14 09:39:43

标签: sql postgresql timestamp date-range

目前我的表中有一列用于存储日期和时间。该列的数据类型为没有时区的时间戳。所以它的格式为'2011-09-13 11:03:44.537'

我需要检索与日期有关的行。如果我使用:

select * from table where mdate >= '2011-09-13 11:03:44.537'
                      and mdate <= '2011-09-12 11:03:44.537'

它将提供介于“2011-09-13 11:03:44.537”和“2011-09-12 11:03:44.537”之间的值。

但如果我要去:

select * from table where mdate >= '2011-09-13 00:00:00.0'
                      and mdate <= '2011-09-12 00:00:00.0'

没有日期,月份和秒,它没有显示任何行。

如何根据日期从此表中获取值(仅限日期,忽略小时,分钟和秒)?

甚至,该列的日期都带有时间戳,我只需要使用日期搜索它们(忽略时间戳或将小时,分钟和秒数设为0,例如'2011-09-13 00:00:00.0'

2 个答案:

答案 0 :(得分:5)

如果您要将字段的timestamp值转换为date,正如另一个答案中所建议的那样,性能会降低,因为列中的每个值都需要进行转换才能进行比较并且简单索引不能使用。您必须创建一个特殊的index on the expression,如下所示:

CREATE INDEX some_idx ON tbl (cast(mdate AS date));

在这种情况下,查询也应简化为:

SELECT * FROM tbl WHERE mdate::date = '2011-09-12'::date; -- 2nd cast optional

但是,据我所知,您的问题在查询中是一个简单的错字/思考:
切换了上部&amp;下边界。尝试:

SELECT * FROM tbl WHERE mdate >= '2011-09-12 00:00:00.0'
                  AND   mdate <= '2011-09-13 00:00:00.0';

或者,为了简化语法并更精确:

SELECT * FROM tbl WHERE mdate >= '2011-09-12 00:00'
                  AND   mdate <  '2011-09-13 00:00';
  • 无需拼出秒数和分数为0。
  • 您不想包含2011-09-13 00:00,因此请使用<代替<=
    出于同样的原因,请不要在此使用BETWEEN

    WHERE mdate BETWEEN '2011-09-12 00:00' AND '2011-09-13 00:00'

    这将包括第二天的00:00。

另请注意,根据您当前的时区设置解释类型为timestamp [without time zone]的列。日期部分取决于该设置,该设置通常应按预期工作。更多细节:
Ignoring timezones altogether in Rails and PostgreSQL

答案 1 :(得分:1)

只需将时间戳视为日期:

select * 
from table 
where mdate::date >= DATE '2011-09-12' 
  and mdate::date <= DATE '2011-09-13'

表达式mdate::date会将时间戳转换为date类型,这将从值中删除时间部分。

DATE '2011-09-13'是一个(标准)DATE文字,它比仅仅编写'2011-09-13'更健壮,因为它不受任何语言设置的影响。