如何在Postgresql的datetime字段中比较日期?


186

比较PostgreSQL中的日期(Windows中的9.2.4版)时,我一直面临一个奇怪的情况。我的表中有一列说update_date,类型为“没有时区的时间戳”。客户只能在该字段中搜索日期(即:2013-05-03)或带时间的日期(即:2013-05-03 12:20:00)。此列当前所有行的时间戳记值为值,日期部分相同(2013-05-03),但时间部分不同。

当我在本专栏进行比较时,会得到不同的结果。如下所示:

select * from table where update_date >= '2013-05-03' AND update_date <= '2013-05-03' -> No results

select * from table where update_date >= '2013-05-03' AND update_date < '2013-05-03' -> No results

select * from table where update_date >= '2013-05-03' AND update_date <= '2013-05-04' -> results found

select * from table where update_date >= '2013-05-03' -> results found

我的问题是如何使第一个查询成为可能,结果是为什么第三个查询有效但第一个查询不正常?

有人可以帮我吗?提前致谢。

Answers:


274

@Nicolai关于强制转换是正确的,为什么条件对于任何数据都是错误的。我想您更喜欢第一种形式,因为您想避免对输入字符串进行日期操作,对吗?您无需担心:

SELECT *
FROM table
WHERE update_date >= '2013-05-03'::date
AND update_date < ('2013-05-03'::date + '1 day'::interval);

此语法('2013-05-03'::date'1 day'::interval)是否特定于PostgreSQL?
冰雪奇缘》 2015年

5
@FrozenFlame是的。标准语法为CAST('2013-05-03' AS DATE) + CAST('1 day' AS INTERVAL)(IIRC)。因人而异的存在和行为DATEINTERVAL
有人2015年

@FrozenFlame是正确的,如果不将字符串强制转换为日期类型,答案将不起作用。仍然缺少一名演员。::DATE在where子句的第一部分需要添加一个内容
StillLearningToCode

不能WHERE update_date::date = '2013-05-03' 很好地工作,也许可读性更高?
MikeF

@MikeF OP说update_datetimestamp without timezone。我假设该列上有一个索引。您的谓词不会使用该索引。
有人

45

比较update_date >= '2013-05-03'postgres时,将值转换为相同类型以比较值。因此,您的“ 2013-05-03”已转换为“ 2013-05-03 00:00:00”。

因此,对于update_date ='2013-05-03 14:45:00',您的表情将是:

'2013-05-03 14:45:00' >= '2013-05-03 00:00:00' AND '2013-05-03 14:45:00' <= '2013-05-03 00:00:00'

这总是 false

要解决此问题,请将update_date强制转换为date

select * from table where update_date::date >= '2013-05-03' AND update_date::date <= '2013-05-03' -> Will return result

1
强制转换update_date表中的每个值与强制转换查询参数的单个值的效率非常低,并确保服务器将无法利用该列上的索引。我很想为此-1。
某人2013年

3
是的,我同意每个值的转换都是无效的,您可以为此解决方案提供-1。但是我描述了问题的原因,并给出了演示问题的例子。现在,user2866264知道了为什么他的查询不返回预期的行,并将决定哪种解决方案对他的独特情况更好。
Nicolai 2013年

@Nicolai:非常感谢您的回答。遵循您的答案即可。也感谢您的解释。
user2866264 2013年

1
@Nicolai –考虑到您所说的Postgres将日期文字扩展为午夜,如果目标是查找标记在单个日期(5月3日)上的记录,此代码是否正确且效率更高:(SELECT * FROM my_table WHERE update_date >= '2013-05-03' AND update_date < '2013-05-04'; 请注意使用5月4日而不是第三和一个小于号,而不是低于或相等)。
罗勒布尔克


2

使用日期转换将其与日期进行比较:请尝试以下操作:

select * from table 
where TO_DATE(to_char(timespanColumn,'YYYY-MM-DD'),'YYYY-MM-DD') = to_timestamp('2018-03-26', 'YYYY-MM-DD')
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.