在 PostgreSQL 中比较日期时间字段中的日期

Bilal Shahid 2024年2月15日
  1. PostgreSQL 中的基本日期比较运算符
  2. 使用 <> 运算符比较 PostgreSQL 中日期时间字段中的日期
  3. 在 PostgreSQL 中使用比较运算符比较日期时间字段中的日期时的自定义查询修改
  4. 使用 RANGE 类型比较 PostgreSQL 中日期时间字段中的日期
  5. 使用 DATA TYPE FORMATTING 函数比较 PostgreSQL 中日期时间字段中的日期
  6. 在 PostgreSQL 中使用 BETWEEN 运算符进行范围替换以比较日期时间字段中的日期
在 PostgreSQL 中比较日期时间字段中的日期

PostgreSQL 中的日期可以使用时间戳、日期或时间来实现。时间戳是日期和时间的串联,而日期以格式表示; YYYY-MM-DD

在我们的上一篇文章中,我们了解了如何在 PostgreSQL 中操作时间戳并从中减去天、小时、月和年。今天我们将研究 DATE 类型的比较运算符,看看我们如何使用它们来为我们带来好处。

PostgreSQL 中的基本日期比较运算符

PostgreSQL 为其 DATETIME 或时间戳格式定义了一组输入。可以在下表中查看它们:

日期时间表

而 TIME 可以有以下所有语法的输入:

时间表

对于时间戳,你可以使用以下语法:

TIMESTAMP '2019-01-01'

请记住,日期可以与所有其他 DATE 类型进行比较,但只能与类似的类型进行对比。可以采用不同的方式进行比较。

例如,你甚至可以使用 PostgreSQL 文档定义的 OVERLAP() 函数来检查重叠日期并返回 TRUE 或 FALSE。

现在让我们继续了解可用于比较两个日期的各种运算符。

使用 <> 运算符比较 PostgreSQL 中日期时间字段中的日期

一个简单的比较查询可以如下:

SELECT '2021-01-01' < '2022-01-01'

上面将返回一个值 TRUE。

SELECT '2021-01-01' > '2022-01-01'

你还可以使用其他比较运算符,例如; <=>==

如果你使用代表 NOT EQUAL 的 <>!=,则上面将返回 TRUE,因为两个日期不相似。

PostgreSQL 文档指出,比较运算符可用于所有数据类型。并且你不能比较两个以上的日期,因为第一次比较的结果将返回一个 BOOL 值。

并且 BOOL 值不能与 DATETIME 类型或任何其他表示 DATE 和 TIME 的类型进行比较。

上面的运算符还考虑了 TIME 方面。如果你执行以下操作:

select '2021-01-01 08:08:08' < '2021-01-01 10:01:01'

它将再次返回 TRUE,这是正确的,因为前 DATE 的 TIME 小于后者。

你还可以使用 IS DISTINCTIS NOT DISTINCT 运算符,如下所示:

expression IS DISTINCT FROM expression
expression IS NOT DISTINCT FROM expression

这等于 NOT EQUALEQUAL 运算符,但它是另一种选择。但是,如果有 NULL 日期,这将返回 FALSE,如果只有一个为 NULL,则返回 TRUE。

在 PostgreSQL 中使用比较运算符比较日期时间字段中的日期时的自定义查询修改

假设我们有一个时间戳 2021-01-01 08:08:08,我们想将其与 2021-01-01 进行比较。

使用以下查询:

select '2021-01-01 08:08:08' <= '2021-01-01'

这应该返回 TRUE,但它恰好返回 FALSE。

为什么?因为当写 2021-01-01 本身时,它表示 2021 年 12 月 31 日的午夜,意思是这样的:2020-31-31 23:59:59

时间戳 2021-01-01 08:08:08 等于或小于,因为我们的时间戳比我们正在比较的 DATE 提前 9 小时。

要删除这个异常,我们必须告诉我们的 PostgreSQL 服务器不要自动在我们的 DATE 字符串中放入 TIME。我们可以使用 CAST 到 DATE 类型来解决这个问题。

为什么?因为 PostgreSQL 列出 DATE 如下:

date	4 bytes	date (no time of day)

这意味着它不包括 TIME。所以现在你可以继续使用下面的查询,它会运行得很好。

select '2021-01-01 08:08:08' <= '2021-01-01'::date

或以下内容:

select '2021-01-01 08:08:08'::date <= '2021-01-01'

使用 RANGE 类型比较 PostgreSQL 中日期时间字段中的日期

那么 PostgreSQL 中的范围是什么?正如你可能已经猜到的那样,RANGE 表示存在的任何数据类型的值的范围。

RANGES 还包括以下配置:

tsrange - Range of timestamp without time zone

tstzrange - Range of timestamp with time zone

daterange - Range of date

假设你运行以下查询;

select '[2021-01-01,2021-01-01]'::tsrange

这将返回如下内容:

tsrange 输出

让我们先了解它是如何工作的,然后修改它以进行 DATE 比较。

RANGE 内的括号称为 EXCLUSIVEINCLUSIVE 边界。EXCLUSIVE 边界表示这样的括号; (or)INCLUSIVE 代表这样的括号; [或者]

如果你使用 EXCLUSIVE 括号编写,它将从 RANGE 中排除以下值。所以如果我们有类似 (3,5) 的东西,它会返回一个范围为 [4]

但是,如果我们有; [3,5),它现在将返回 [3,4],如果 (3,5],它将返回 [4,5]

因此,如果我们想查看两个日期之间的范围,我们可以使用上面的查询。但是它是如何比较日期的呢?

假设我们要检查 2020-12-31 是否小于 2021-01-01。所以我们可以这样写:

select '[2020-12-31,2021-01-01]'::tsrange

它会告诉我们两者的范围内是否有任何日期以及它们是否按顺序排列。这意味着 2021-12-30 在 RANGE 中小于 2021-01-01 或晚于后者的日期。

如果我们反转这一点并按如下方式运行查询:

select '[2021-01-01,2020-12-31]'::tsrange

你会注意到一个错误:

输出:

ERROR:  range lower bound must be less than or equal to range upper bound
LINE 1: select '[2021-01-01,2020-12-31]'::tsrange

这告诉我们前者的 DATE 不小于后者。所以我们可以用它来进行比较。我们希望我们不需要告诉你有关 TSRANGE 的内容,因为上面已经提到过它和其他类型。

如果你尝试运行以下命令,该错误将再次重现:

select '[2021-01-01 09:09:10,2021-01-01 09:09:09]'::tsrange

除了 TSRANGE,你甚至可以使用 DATERANGE CAST。

使用 DATA TYPE FORMATTING 函数比较 PostgreSQL 中日期时间字段中的日期

数据类型表

另一个与第一个解决方案中提供的比较相似的重要比较查询编写如下:

Select to_date(to_date('2018-03-26','YYYY-MM-DD')::text,'YYYY-MM-DD'::text) =
to_timestamp('2018-03-26', 'YYYY-MM-DD')

那么这里发生了什么?我们将 DATE 类型与时间戳进行比较。

这是可能的,因为 DATE 可以与所有其他类型的 DATES 进行比较。所以函数 TO_DATE 返回一个 DATE 类型,因为它使用参数作为 (text, text)

TO_DATE 的第一次调用将多个 TEXTS 转换为 DATE 类型,然后再次将其转换为外部 TO_DATE 函数的 TEXT。

PostgreSQL 倾向于为第二个参数返回错误,因为它以某种方式混淆了 STRING 并将其称为 UNKNOWN 而不是 TEXT。因此,我们也向它添加了一个 EXPLICIT TYPECAST。

其余的很容易理解,并将很好地服务于我们的目的。

在 PostgreSQL 中使用 BETWEEN 运算符进行范围替换以比较日期时间字段中的日期

使用如下查询:

select '2021-01-01' between '2020-01-01' and '2022-01-01'

或下面的查询:

select '2021-01-01' not between '2020-01-01' and '2022-01-01'

BETWEEN 运算符如果介于两者之间,则返回 TRUE,而 NOT BETWEEN 如果不在提供的范围的中间,则返回 FALSE。

所以今天,我们了解了我们可以实现使用运算符来比较各种 DATE 类型的不同方法。我们希望你自己进一步探索它们,尽管我们已尽最大努力涵盖所有解决方案。

但是技术不断发展壮大,迟早会有更新、更好的功能取代上面给出的功能。

作者: Bilal Shahid
Bilal Shahid avatar Bilal Shahid avatar

Hello, I am Bilal, a research enthusiast who tends to break and make code from scratch. I dwell deep into the latest issues faced by the developer community and provide answers and different solutions. Apart from that, I am just another normal developer with a laptop, a mug of coffee, some biscuits and a thick spectacle!

GitHub