|
|
|
|
|
我們?cè)贛ySQL計(jì)算兩日期時(shí)間差時(shí),往往是使用算術(shù)表達(dá)式來(lái)計(jì)算直接獲得結(jié)果,但當(dāng)兩字段數(shù)據(jù)類型不同時(shí),獲得的結(jié)果是一串難以理解的數(shù)字。為此,我們需要更新這種寫(xiě)法,要以獲得易理解易閱讀和易用結(jié)果為目標(biāo),這是本文的初衷,而一個(gè)很簡(jiǎn)單的CAST()
函數(shù),就能滿足我們的要求。
介紹
CAST()
函數(shù)用于將某種數(shù)據(jù)類型的表達(dá)式顯式轉(zhuǎn)換為另一種數(shù)據(jù)類型。CAST()
函數(shù)的參數(shù)是一個(gè)表達(dá)式,它包括用AS
關(guān)鍵字分隔的源值和目標(biāo)數(shù)據(jù)類型。
語(yǔ)法:
CAST (expression AS data_type)
示例
運(yùn)行以下查詢,以start_time
減去end_time
計(jì)算小時(shí)數(shù)(提示:end_time
數(shù)據(jù)類型是TIMESTAMP
,start_time
數(shù)據(jù)類型是TIME
)。
SELECT runner_name, race_name, end_time - start_time
AS total_time
FROM race_results;
輸出:
Output
+-------------+---------------+----------------+
| runner_name | race_name | total_time |
+-------------+---------------+----------------+
| bolt | 1600_meters | 20220918000630 |
| bolt | 5K | 20221019002231 |
| bolt | 10K | 20221120003805 |
| bolt | half_marathon | 20221221013904 |
| bolt | full_marathon | 20230122032310 |
| felix | 1600_meters | 20220918000715 |
| felix | 5K | 20221019003050 |
| felix | 10K | 20221120011017 |
| felix | half_marathon | 20221221021157 |
| felix | full_marathon | 20230122040210 |
+-------------+---------------+----------------+
10 rows in set (0.00 sec)
可以看到,輸出包含一列很長(zhǎng)的輸出,該輸出跟隨表中設(shè)置的TIMESTAMP
數(shù)據(jù)類型。
因?yàn)槟阏谑褂镁哂胁煌瑪?shù)據(jù)類型(end_time
保存TIMESTAMP
值而start_time
保存TIME
值)的兩列執(zhí)行操作,所以數(shù)據(jù)庫(kù)在打印操作結(jié)果時(shí)不知道要使用哪種數(shù)據(jù)類型。相反,它將兩個(gè)值都轉(zhuǎn)換為整數(shù),以便可以執(zhí)行操作,從而在total_time
列中生成長(zhǎng)數(shù)字。
為了幫助使這些數(shù)據(jù)更易于閱讀和解釋,你可以使用CAST()
函數(shù)將這些長(zhǎng)整數(shù)值轉(zhuǎn)換為TIME
數(shù)據(jù)類型。為此,請(qǐng)先以CAST
開(kāi)頭,跟著用左括號(hào),然后是要轉(zhuǎn)換的值,再加上AS
關(guān)鍵字和要將其轉(zhuǎn)換成的數(shù)據(jù)類型,最后加上右括號(hào)。
以下查詢與前面的示例相同,但使用CAST()
函數(shù)將total_time
列轉(zhuǎn)換為TIME
數(shù)據(jù)類型:
SELECT runner_name, race_name, CAST(end_time - start_time AS time)
AS total_time
FROM race_results;
輸出:
Output
+-------------+---------------+------------+
| runner_name | race_name | total_time |
+-------------+---------------+------------+
| bolt | 1600_meters | 00:06:30 |
| bolt | 5K | 00:22:31 |
| bolt | 10K | 00:38:05 |
| bolt | half_marathon | 01:39:04 |
| bolt | full_marathon | 03:23:10 |
| felix | 1600_meters | 00:07:15 |
| felix | 5K | 00:30:50 |
| felix | 10K | 01:10:17 |
| felix | half_marathon | 02:11:57 |
| felix | full_marathon | 04:02:10 |
+-------------+---------------+------------+
10 rows in set (0.00 sec)
CAST
將輸出中的數(shù)據(jù)值轉(zhuǎn)換為TIME
,使其更易于閱讀和理解,以及使用。
使用聚合函數(shù)
現(xiàn)在,讓我們使用一些聚合函數(shù)結(jié)合CAST
來(lái)查找最短、最長(zhǎng)和總時(shí)間結(jié)果。
首先,MIN
聚合函數(shù)查詢最少(或最短)時(shí)間。同樣,為了清楚起見(jiàn),希望使用CAST
將TIMESTAMP
數(shù)據(jù)值轉(zhuǎn)換為TIME
數(shù)據(jù)值。請(qǐng)注意,當(dāng)使用本例中的兩個(gè)函數(shù)時(shí),需要兩對(duì)括號(hào),并且總小時(shí)數(shù) ( end_time
- start_time
) 的計(jì)算應(yīng)嵌套在其中一對(duì)括號(hào)內(nèi)。最后,添加一個(gè)GROUP BY
子句來(lái)根據(jù)runner_name列組織這些值,以便輸出顯示兩個(gè)跑步者的比賽結(jié)果:
SELECT runner_name, MIN(CAST(end_time - start_time AS time)) AS min_time
FROM race_results GROUP BY runner_name;
輸出:
Output
+-------------+----------+
| runner_name | min_time |
+-------------+----------+
| bolt | 00:06:30 |
| felix | 00:07:15 |
+-------------+----------+
2 rows in set (0.00 sec)
此輸出顯示每個(gè)跑步者的最短跑步時(shí)間,在本例中,Bolt 至少為 6 分 30 秒,F(xiàn)elix 為 7 分 15 秒。
接下來(lái),找到每個(gè)跑步者的最長(zhǎng)時(shí)間。可以使用與上一個(gè)查詢相同的語(yǔ)法,但這次替換MIN
為MAX
:
SELECT runner_name, MAX(CAST(end_time - start_time AS time)) AS max_time
FROM race_results GROUP BY runner_name;
輸出:
Output
+-------------+----------+
| runner_name | max_time |
+-------------+----------+
| bolt | 03:23:10 |
| felix | 04:02:10 |
+-------------+----------+
2 rows in set (0.00 sec)
這個(gè)輸出告訴我們,Bolt 最長(zhǎng)的運(yùn)行時(shí)間總共是 3 小時(shí) 23 分 10 秒;而 Felix 一共是 4 小時(shí) 2 分 10 秒。
現(xiàn)在讓我們查詢一些關(guān)于每個(gè)跑步者跑步總小時(shí)數(shù)的高級(jí)信息。對(duì)于此查詢,結(jié)合SUM
聚合函數(shù)以查找基于end_time - start_time
的總小時(shí)數(shù),并用CAST
將這些數(shù)據(jù)值轉(zhuǎn)換為TIME
。不要忘記包括GROUP BY
組織兩個(gè)跑步者結(jié)果的值:
SELECT runner_name, SUM(CAST(end_time - start_time AS time))
AS total_hours FROM race_results GROUP BY runner_name;
輸出:
Output
+-------------+-------------+
| runner_name | total_hours |
+-------------+-------------+
| bolt | 52880 |
| felix | 76149 |
+-------------+-------------+
2 rows in set (0.00 sec)
這個(gè)輸出顯示了 MySQL 的解釋,它實(shí)際上是以整數(shù)計(jì)算總時(shí)間。如果我們將這些結(jié)果解讀為時(shí)間,Bolt 的總時(shí)間為 5 小時(shí) 28 分 80 秒;Felix 的總時(shí)間為 7 小時(shí) 61 分 49 秒。這表明它是以整數(shù)而不是時(shí)間計(jì)算的。如果在不同的 DBMS(例如 PostgreSQL)中嘗試此操作,則相同的查詢看起來(lái)會(huì)略有不同:
SELECT runner_name, SUM(CAST(end_time - start_time AS time))
AS total_hours FROM race_results GROUP BY runner_name;
輸出:
Output
runner_name | total_hours
-------------+-------------
felix | 10:01:44
bolt | 06:09:20
(2 rows)
在這種情況下,PostgreSQL 中的查詢將值解釋為時(shí)間并按時(shí)間計(jì)算,因此 Felix 的結(jié)果分解為總共 10 小時(shí)、1 分鐘和 44 秒;而 Bolt 的時(shí)間是 6 小時(shí) 9 分 20 秒。這是一個(gè)示例,說(shuō)明各種 DBMS 以不同方式解釋數(shù)據(jù)值,即使它使用相同的查詢和數(shù)據(jù)集。
總結(jié)
本教程僅對(duì) SQL 中的日期和時(shí)間使用了加法和減法運(yùn)算,但你可以將日期和時(shí)間值與任何數(shù)學(xué)表達(dá)式一起使用。從我們的數(shù)學(xué)表達(dá)式和聚合函數(shù)指南中了解更多信息,并在你的日期和時(shí)間查詢中試用它們。