PostgreSQL BETWEEN 运算符的行为不同
Posted
技术标签:
【中文标题】PostgreSQL BETWEEN 运算符的行为不同【英文标题】:PostgreSQL BETWEEN operator behaving differently 【发布时间】:2019-06-12 11:03:10 【问题描述】:我正在使用 sql 查询来提取已部署解决方案的几天数据
我以下列方式使用查询
select column1, column2, column3, column 4
where <condition 1> AND <condition 2> AND
created_timestamp BETWEEN '05-31-2019' AND '06-11-2019'
现在它用于获取所有列的值,并按预期按条件过滤数据,除了这里有一个转折。它未获取作为上限提供的 6 月 11th 日期的数据。
现在据我所知,运算符之间包括所提供范围的两个端点。
更让我困惑的是,它以某种方式包含了 5 月 31st 日期的数据,这是上限。
我需要知道算子之间是否包含范围的端点(尤其是在postgresql中不认为所以它会改变只是想确认)?
即使它包含/排除,它对于两个端点的行为也应该相同我不理解有偏见的行为,有人对此有所了解吗?
【问题讨论】:
【参考方案1】:尝试使用正确的日期文字:
SELECT column1, column2, column3, column4
FROM your_table
WHERE created_timestamp BETWEEN '2019-05-31' AND '2019-06-11';
2019-05-31
采用 ISO 8601 格式,在任何模式下都明确表示 2019 年 5 月 31 日。
您可以阅读有关日期/时间类型规则的更多信息here。
编辑:
6 月 11 日的数据未显示的原因是使用2011-06-11
作为范围的上限与使用2011-06-11 00:00:00
相同。也就是说,它只包括 6 月 11 日的午夜。为了缓解这种情况,请使用 6 月 12 日作为上限:
SELECT column1, column2, column3, column4
FROM your_table
WHERE created_timestamp >= '2019-05-31' AND created_timestamp < '2019-06-12';
【讨论】:
【参考方案2】:我假设created_timestamp
是timestamp
(有或没有时区)。
您使用的文字 06-11-2019
对应于该日期的午夜:
SELECT '06-11-2019'::timestamp with time zone;
timestamptz
------------------------
2019-06-11 00:00:00+02
(1 row)
因此,结果不包括 6 月 11 日的数据也就不足为奇了。
有两种前进方式:
使用第二天和<
运算符:
... WHERE created_timestamp >= '05-31-2019' AND created_timestamp < '06-12-2019'
将时间戳转换为date
:
... WHERE date(created_timestamp) BETWEEN '05-31-2019' AND '06-11-2019'
第二个选项不能使用created_timestamp
上的索引(但它可以使用date(created_timestamp)
上的索引)。
您的查询取决于 DateStyle
的 PostgreSQL 设置,因此请确保该设置始终符合您的需要。
【讨论】:
是的,你是对的,它是一个时间戳(没有时区)所以你的意思是说'BETWEEN'运算符基本上会转换成这个 05-31-2019 00:00:00.00 = 06-11-2019 00:00:00.00 是这样吗? 基本上是的,除非你把正确的不等号弄错了——它应该是<=
。
啊,是的,我没看到,谢谢!!感谢您澄清困惑,这真的很有帮助:)【参考方案3】:
如果 created_timestamp 是一个日期/时间值,而不仅仅是一个日期,那么 6 月 11 日午夜(00:00 小时)之后的所有内容都将在 BETWEEN 之外。所以你也许可以这样做
date_trunc('day', created_timestamp) BETWEEN '2019-05-31' AND '2019-06-11'
正如已经指出的,日期应该是 yyyy-mm-dd 格式。正如 Gordon 所提到的,在这种情况下,它们不需要强制转换为 date,但他说得对,在某些情况下,您确实需要强制转换为 date,这样做并没有什么坏处。
【讨论】:
【参考方案4】:据推测,created_timestamp
实际上是日期/时间格式。所以,比较日期/时间值,而不是字符串:
created_timestamp >= '2019-05-21'::date and
created_timestamp < '2019-06-11'::date
请注意,我将between
更改为两个不等式。这意味着当created_timestamp
实际上有一个时间分量时,代码的行为与预期一样。
【讨论】:
但 PostgreSQL 可以将字符串文字(类型unknown
)转换为 timestamp
。以上是关于PostgreSQL BETWEEN 运算符的行为不同的主要内容,如果未能解决你的问题,请参考以下文章