在 PostgreSQL 中比較日期時間欄位中的日期

Bilal Shahid 2023年1月30日
  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