《PostgreSQL 開發指南》 第 17 篇 常用函數(二)

上一篇我們介紹 PostgreSQL 中常用的數學函數和字符函數。現在我們繼續學習常用的日期時間函數以及類型轉換函數。

日期時間函數

PostgreSQL 提供了以下日期和時間運算的算術運算符。

運算符 示例 結果
+ date ‘2001-09-28’ + integer ‘7’ date ‘2001-10-05’
+ date ‘2001-09-28’ + interval ‘1 hour’ timestamp ‘2001-09-28 01:00:00’
+ date ‘2001-09-28’ + time ‘03:00’ timestamp ‘2001-09-28 03:00:00’
+ interval ‘1 day’ + interval ‘1 hour’ interval ‘1 day 01:00:00’
+ timestamp ‘2001-09-28 01:00’ + interval ‘23 hours’ timestamp ‘2001-09-29 00:00:00’
+ time ‘01:00’ + interval ‘3 hours’ time ‘04:00:00’
- - interval ‘23 hours’ interval ‘-23:00:00’
- date ‘2001-10-01’ - date ‘2001-09-28’ integer ‘3’ (days)
- date ‘2001-10-01’ - integer ‘7’ date ‘2001-09-24’
- date ‘2001-09-28’ - interval ‘1 hour’ timestamp ‘2001-09-27 23:00:00’
- time ‘05:00’ - time ‘03:00’ interval ‘02:00:00’
- time ‘05:00’ - interval ‘2 hours’ time ‘03:00:00’
- timestamp ‘2001-09-28 23:00’ - interval ‘23 hours’ timestamp ‘2001-09-28 00:00:00’
- interval ‘1 day’ - interval ‘1 hour’ interval ‘1 day -01:00:00’
- timestamp ‘2001-09-29 03:00’ - timestamp ‘2001-09-27 12:00’ interval ‘1 day 15:00:00’
* 900 * interval ‘1 second’ interval ‘00:15:00’
* 21 * interval ‘1 day’ interval ‘21 days’
* double precision ‘3.5’ * interval ‘1 hour’ interval ‘03:30:00’
/ interval ‘1 hour’ / double precision ‘1.5’ interval ‘00:40:00’

PostgreSQL 還提供了大量用於日期和時間數據處理的函數。

計算時間間隔

age(timestamp, timestamp) 函數用於計算兩個時間點之間的間隔,age(timestamp) 函數用於計算當前日期的凌晨 12 點到該時間點之間的間隔。

SELECT age(timestamp '2020-12-31', timestamp '2020-01-01'), age(timestamp '2020-01-01');
age            |age          |
---------------|-------------|
11 mons 30 days|2 mons 2 days|

2020 年 12 月 31 日到 2020 年 01 月 01 日之間有 11 個月零 30 天;今天(2020 年 03 月 03 日)距離 2020 年 01 月 01 日已經過了 2 個月零 2 天。

獲取時間中的信息

date_part(text, timestamp)extract(field from timestamp) 函數用於獲取日期時間中的某一部分,例如年份、月份、小時等;date_part(text, interval)extract(field from interval) 函數用於獲取時間間隔中的某一部分。

SELECT date_part('year', timestamp '2020-03-03 20:38:40'), extract(year from timestamp '2020-03-03 20:38:40'),
       date_part('month', interval '1 years 5 months'), extract(month from interval '1 years 5 months');
date_part|date_part|date_part|date_part|
---------|---------|---------|---------|
     2020|     2020|        5|        5|

通過返回字段的標題可以看出,extract 函數實際上也是調用了 date_part 函數,只是參數方式不同。這兩個函數支持獲取的信息包括:

  • century,世紀;
  • day,對於 timestamp,返回月份中的第幾天;對於 interval,返回天數;
  • decade,年份除以 10;
  • dow,星期天(0)到星期六(6);
  • doy,一年中的第幾天,(1 - 365/366);
  • epoch,對於 timestamp with time zone,返回從1970-01-01 00:00:00 UTC 到該時間的秒數;對於 date 和 timestamp,返回本地時間的 1970-01-01 00:00:00 到該時間的秒數;對於 interval,返回以秒數表示的該時間間隔;
  • hour,小時(1 - 23);
  • isodow,ISO 8601 標準中的星期一(1)到星期天(7);
  • isoyear,ISO 8601 標準定義的日期所在的年份。每年從包含 1 月 4 日的星期一開始,2017 年 01 月 01 日屬於 2016 年;
  • microseconds,微秒,包含秒和小數秒在內的數字乘以 1000000;
  • millennium,千年;
  • milliseconds,毫秒,包含秒和小數秒在內的數字乘以 1000;
  • minute,分鐘,(0 - 59);
  • month,月份;
  • quarter,季度,(1 - 4);
  • second,秒數,包含小數秒;
  • timezone,UTC 時區,單位爲秒;
  • timezone_hour,UTC 時區中的小時部分;
  • timezone_minute,UTC 時區中的分鐘部分;
  • week,ISO 8601 標準中的星期幾,每年從第一個星期四所在的一週開始;
  • year,年份。

截斷日期/時間

date_trunc(field, source [, time_zone ]) 函數用於將 timestamp、timestamp with time zone、date、time 或者 interval 數據截斷到指定的精度。

SELECT date_trunc('year', timestamp '2020-03-03 20:38:40'),
       date_trunc('day', timestamptz '2020-03-03 20:38:40+00', 'Asia/Shanghai'),
       date_trunc('hour', interval '2 days 3 hours 40 minutes');
date_trunc         |date_trunc         |date_trunc     |
-------------------|-------------------|---------------|
2020-01-01 00:00:00|2020-03-04 00:00:00|2 days 03:00:00|

date_trunc 函數支持以下截斷精度:

  • microseconds
  • milliseconds
  • second
  • minute
  • hour
  • day
  • week
  • month
  • quarter
  • year
  • decade
  • century
  • millennium

創建日期/時間

make_date(year int, month int, day int) 函數用於創建一個日期:

SELECT make_date(2020, 03, 15);
make_date |
----------|
2020-03-15|

make_interval(years int DEFAULT 0, months int DEFAULT 0, weeks int DEFAULT 0, days int DEFAULT 0, hours int DEFAULT 0, mins int DEFAULT 0, secs double precision DEFAULT 0.0) 函數通過指定年、月、日等信息創建一個時間間隔。

SELECT make_interval(days => 1, hours => 5);
make_interval |
--------------|
1 day 05:00:00|

make_time(hour int, min int, sec double precision) 函數通過指定小時、分鐘和秒數創建一個時間。

SELECT make_time(1, 2, 30.5);
  make_time|
-----------|
 01:02:30.5|

make_timestamp(year int, month int, day int, hour int, min int, sec double precision) 函數通過指定年、月、日、時、分、秒創建一個時間戳。

SELECT make_timestamp(2020, 3, 15, 8, 20, 23.5);
make_timestamp       |
---------------------|
2020-03-15 08:20:23.5|

make_timestamptz(year int, month int, day int, hour int, min int, sec double precision, [ timezone text ]) 函數通過指定年、月、日、時、分、秒創建一個帶時區的時間戳。如果沒有指定時區,使用當前時區。

SELECT make_timestamptz(2020, 3, 15, 8, 20, 23.5);
make_timestamptz        |
------------------------|
2020-03-15 08:20:23.5+08|

to_timestamp(double precision) 函數將 Unix 時間戳(自從 1970-01-01 00:00:00+00 以來的秒數)轉換爲 PostgreSQL 時間戳數據。

SELECT to_timestamp(1583152349);
to_timestamp          |
----------------------|
2020-03-02 20:32:29+08|

獲取系統時間

PostgreQL 提供了大量用於獲取系統當前日期和時間的函數,例如 current_date、current_time、current_timestamp、clock_timestamp()、localtimestamp、now()、statement_timestamp() 等;同時還支持延遲語句執行的 pg_sleep() 等函數,具體可以可以參考這篇文章

時區轉換

AT TIME ZONE 運算符用於將 timestamp without time zone、timestamp with time zone 以及 time with time zone 轉換爲指定時區中的時間。

SELECT TIMESTAMP '2020-03-03 20:38:40' AT TIME ZONE 'Asia/Shanghai',
       TIMESTAMP WITH TIME ZONE '2020-03-03 20:38:40-05:00' AT TIME ZONE 'Asia/Shanghai',
       TIME WITH TIME ZONE '20:38:40-05:00' AT TIME ZONE 'Asia/Shanghai';
timezone              |timezone           |timezone   |
----------------------|-------------------|-----------|
2020-03-03 20:38:40+08|2020-03-04 09:38:40|09:38:40+08|

timezone(zone, timestamp) 函數等價於 SQL 標準中的 timestamp AT TIME ZONE zone

📝還有一些關於日期時間的函數,可以參考官方文檔

類型轉換函數

類型轉換函數用於將數據從一種類型轉換爲另一種類型。

CAST 函數

CAST ( expr AS data_type ) 函數用於將 expr 轉換爲 data_type 數據類型;PostgreSQL 類型轉換運算符(::)也可以實現相同的功能。例如:

SELECT CAST ('15' AS INTEGER), '2020-03-15'::DATE;
int4|date      |
----|----------|
  15|2020-03-15|

如果數據無法轉換爲指定的類型,將會返回錯誤:

SELECT CAST ('A15' AS INTEGER);
SQL 錯誤 [22P02]: 錯誤: 無效的類型 integer 輸入語法: "A15"
  位置:14

to_date 函數

to_date(string, format) 函數用於將字符串 string 按照 format 格式轉換爲日期類型。

SELECT to_date('2020/03/15','YYYY/MM/DD');
to_date   |
----------|
2020-03-15|

其中,YYYY 代表 4 位數的年;MM 代表兩位數的月;DD 代表兩位數的日。更多的格式選項可以參考官方文檔

to_timestamp 函數

to_timestamp(string, format) 函數用於將字符串 string 按照 format 格式轉換爲 timestamp with time zone 類型。

SELECT to_timestamp('2020-03-15 19:08:00.678', 'YYYY-MM-DD HH24:MI:SS.MS');
to_timestamp              |
--------------------------|
2020-03-15 19:08:00.678+08|

其中,HH24 表示 24 小時制的小時;MI 表示分鐘;SS 表示秒數;MS 表示毫秒數。

to_char 函數

to_char(expre, format) 函數用於將 timestamp、interval、integer、double precision 或者 numeric 類型的值轉換爲指定格式的字符串。

SELECT to_char(current_timestamp, 'HH24:MI:SS'),
       to_char(interval '5h 12m 30s', 'HH12:MI:SS'),
       to_char(-125.8, '999D99');
to_char |to_char |to_char|
--------|--------|-------|
21:30:22|05:12:30|-125.80|

其中,格式中的 9 代表數字位;D 代表小數點。關於數字的格式化選項可以參考官方文檔

to_number 函數

to_number(string, format) 函數用於將字符串轉換爲數字。

SELECT to_number('¥125.8', 'L999D9');
to_number|
---------|
    125.8|

其中,格式字符串中的 L 表示本地貨幣符號。

隱式類型轉換

除了顯式使用類型轉換函數或運算符之外,很多時候 PostgreSQL 會自動執行數據類型的隱式轉換。

SELECT 1+'2', 'todo: '||current_timestamp;
?column?|?column?                          |
--------|----------------------------------|
       3|todo:2020-03-09 21:49:49.370621+08|

下一篇我們將會介紹 PostgreSQL 中的子查詢(Subquery)。

歡迎關注❤️、點贊👍、轉發📣!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章