MySQL快速回顧:計算欄位與函數

来源:https://www.cnblogs.com/flunggg/archive/2020/01/16/12200198.html
-Advertisement-
Play Games

9.1 計算欄位 存儲在資料庫表中的數據一般不是應用程式所需要的格式。比如: 如果想要在一個欄位中既顯示公司名,又顯示公式的地址,但這兩個信息一般包含在不同的表列中。 城市、州和郵政編碼存儲在不同的列中,但郵件標簽列印程式卻需要把它們作為一個恰當格式的欄位檢索出來。 列數據是大小寫混合的,但報表程式 ...


9.1 計算欄位

存儲在資料庫表中的數據一般不是應用程式所需要的格式。比如:

  • 如果想要在一個欄位中既顯示公司名,又顯示公式的地址,但這兩個信息一般包含在不同的表列中。
  • 城市、州和郵政編碼存儲在不同的列中,但郵件標簽列印程式卻需要把它們作為一個恰當格式的欄位檢索出來。
  • 列數據是大小寫混合的,但報表程式需要把所有數據按大寫表示出來。

在上面舉的例子中,存儲在表中的數據都不是應用程式所需要的。我們需要直接資料庫中檢索出轉換、計算或格式化過的數據;而不是檢索出數據,然後在客戶機應用程式或報告程式中重新格式化。

所以就需要計算欄位。計算欄位並不實際存儲於資料庫表中,而是運行時在SELECT語句內創建的。

這裡的欄位(field)基本上跟列(column)的意思相同,經常互換使用,不過資料庫列一般稱為列,而術語欄位通常用在計算欄位的連接上。

可在SQL語句內完成的許多轉換和格式化工作都可以直接在客戶機應用程式內完成。但是一般來說,在資料庫伺服器上完成這些操作比在客戶機中完成要快得多,因為DBMS是設計來快速地完成這種處理的。

9.1.1 計算欄位的使用

舉一個創建由兩列組成的標題的簡單例子。

vendors表包含供應商名和位置信息。假如要生成一個供應商報表,需要在供應商的名字中按照name(location)這樣的格式列出供應商的位置。

此報表需要單個值,而表中數據存儲在兩個列vend_name和vend_country中。此外,需要用括弧將vend_country括起來,這些東西都沒有明確存儲在資料庫表中。來看看如何用SELECT來編寫這樣的格式。

拼接(concatenate)將值聯結到一起構成單個值。

解決的方法就是將兩個列拼接起來。在MySQL的SELECT語句中,可使用CONCAT()函數來拼接兩個列。

多數DBMS使用+或者||來實現拼接,而MySQL則使用Concat()函數來實現。當把SQL語句轉換成MySQL語句時一定要把這個區別銘記在心。

結果:

SELECT CONCAT(vend_name, '(', vend_country, ')')
 FROM vendors
 ORDER BY vend_name;

輸出:

+-------------------------------------------+
| CONCAT(vend_name, '(', vend_country, ')') |
+-------------------------------------------+
| ACME(USA)                                 |
| Anvils R Us(USA)                          |
| Jet Set(England)                          |
| LT Supplies(USA)                          |
+-------------------------------------------+
4 rows in set (0.06 sec)

解釋:

  • CONCAT()拼接串),即把多個串連接起來形成一個較長的串。CONCAT()需要一個或多個指定的串,各個串之間用逗號分隔。(關於更多函數的使用後面會講)
  • 上面的SELECT語句連接以下4個元素:
    • 存儲在vend_name列中的名字;
    • 包括一個空格和一個左圓括弧的串;
    • 存儲在vend_country列中的國家;
    • 包括一個右圓括弧的串。

9.1.2 使用別名

你拿上面那條語句去執行,會發現新計算出的列名,列名好長而且列名的意義不能明確看出。實際上它是沒有名稱,它只是一個值。如果僅在SQL查詢工具中查看一下結果,這樣沒什麼不好。但是,一個未命名的列不能用於客戶機應用中,因為客戶機沒有辦法引用它。這時候SQL就引出別名。

別名(alias)是一個欄位或值的替換名。別名用AS關鍵字賦予。

使用別名修改上面的SQL語句

SELECT CONCAT(vend_name, '(', vend_country, ')')
 AS vend_title
 FROM vendors
 ORDER BY vend_name;

AS也可省略,只要在需要重命名的後面空一格。

SELECT CONCAT(vend_name, '(', vend_country, ')')
  vend_title
 FROM vendors
 ORDER BY vend_name;

輸出:

+------------------+
| vend_title       |
+------------------+
| ACME(USA)        |
| Anvils R Us(USA) |
| Jet Set(England) |
| LT Supplies(USA) |
+------------------+
4 rows in set (0.06 sec)

這樣任何客戶機都可以按別名引用這個列,看起來是一個實際的表列一樣。

別名不止用於計算欄位中,還可以在實際的表列名包含不符合規定的字元(含空格)時重新命名它,在原來的名字含混或容易誤解時擴充它,等。但記住,並不是真正會去重命名錶中的實際列名。

別名有時候也稱為導出列(derived column),不管稱為什麼,它們所代表的都是相同的東西。

9.1.3 執行算術計算

計算欄位的另一常見用途是讀檢索出的數據進行算術計算。比如,一個訂單表order中含有物品價格price和物品數量quantity,需要求物品總價格。那麼只需要 物品價格乘以物品數據即可。

SELECT order_id, order_price*order_quantiry 
 AS expanded_price
 FROM order;

MySQL算術操作符:+、-、*、/。

SELECT可用通過使用計算欄位來測試。

SELECT 2*3;

小結:介紹了計算欄位以及如何創建計算欄位。此外還學瞭如何創建和使用別名,以便應用程式能引用計算欄位。

9.2 函數

SQL支持利用函數來處理數據。

可移植性(portable): 能運行在多個系統上的代碼。
多數SQL語句是可移植的,在SQL實現之間有差異時,這些差異通常不那麼難處理。而函數的可移植性卻不強。幾乎每種主要的DBMS的實現都支持其他實現不支持的函數,而且有時差異還很大。
為了代碼的可移植性,很多SQL程式員不贊成使用特殊實現的功能。雖然這樣有好處,但是不使用這些函數,編寫某些應用程式代碼會很難。
如果決定使用函數,應該保證做好代碼註釋,以便以後你(或其他人)能確切地知道所編寫的SQL代碼的含義。

9.2.1 使用函數

大多數SQL實現支持以下類型的函數

  • 用於處理文本串(如刪除或填充值,轉換值為大寫或小寫)的文本函數
  • 用於在數值上進行算術操作(如返回絕對值,進行代數運算)的數值函數。
  • 用於處理日期和時間值並從這些值中提取特定成分(例如,返回兩個日期之差,檢查日期有效性等)的日期和時間函數。
  • 返回DBMS正使用的特殊信息(如返回用戶登錄信息,檢查版本細節)的系統函數

9.2.2 文本處理函數

之前已經介紹TRIM():去空格的函數。類似的函數如下:
參考:菜鳥教程

函數 說明 演示
LEFT(s,n) 返回字元串 s 的前 n 個字元 返回字元串 runoob 中的前兩個字元:SELECT LEFT('runoob',2) -- ru
RIGHT(s,n) 返回字元串 s 的後 n 個字元 返回字元串 runoob 的後兩個字元:SELECT RIGHT('runoob',2) -- ob
LOWER(s) 將串轉換為小寫 把字元串 Runoob 全轉小寫: SELECT LOWER('Runoob') -- runoob
UPPER(s) 將串轉換為大寫 返回字元串 runoob 全轉小寫:SELECT UPPER('Runoob') -- RUNOOB
TRIM(s) 去掉串的左右空格 去掉字元串 空格runoob空格 的空格:SELECT TRIM(' runoob ') -- runoob
LTRIM(s) 去掉串左邊的空格 去掉字元串 空格runoob空格 的左空格:SELECT LTRIM(' runoob ') -- runoob空格
RTRIM(s) 去掉串右邊的空格 去掉字元串 空格runoob空格 的右空格:SELECT RTRIM(' runoob ') -- 空格runoob
SOUNDEX() 返回串的SOUNDEX值 看下麵的解釋
SUBSTRING(s, start, length) 從字元串 s 的 start 位置截取長度為 length 的子字元串 從字元串 RUNOOB 中的第 2 個位置截取 3個 字元:SELECT SUBSTRING("RUNOOB", 2, 3) AS ExtractString; -- UNO
LOCATE(s1,s) 從字元串 s 中獲取 s1 的開始位置 獲取 b 在字元串 abc 中的位置:SELECT LOCATE('st','myteststring'); -- 5返回字元串 abc 中 b 的位置:SELECT LOCATE('b', 'abc') -- 2
LENGTH() 返回串的長度 返回字元串 runoob 的長度:SELECT LENGTH('runoob') -- 6

上面的SOUNDEX需要進一步解釋:SOUNDEX是一個而將任何文本串轉換為描述其語音表示的字母數字模式的演算法。SOUNDEX考慮了類似的發音字元和音節,使得能對串進行發音比較而不是字母比較。雖然SOUNDEX不是SQL概念,但MySQL(就像很大DBMS一樣)都提供對SOUNDEX的支持。

比如,創建一張表名為customers,表中包含顧客(cust_name)和聯繫名(cust_contact)。

CREATE TABLE customers(
    cust_name varchar(20) PRIMARY KEY,
    cust_contact varchar(20)
);

現在假設有一個顧客Coyote Inc. , 其聯繫名為 Y.Lee。但如果這是輸入錯誤的結果,此聯繫名實際應該是Y.Lie,怎麼辦?顯然,按正確的聯繫名搜索不會返回數據,如下:

SELECT cust_name, cust_contact
FROM customers
WHERE cust_contact = 'Y.Lie';

輸出:

Empty set

現在試下使用SOUNDEX()函數進行搜索,它匹配所有發音類似於Y.Lie的聯繫名:

SELECT cust_name, cust_contact
FROM customers
WHERE SOUNDEX(cust_contact) = SOUNDEX('Y.Lie');

輸出:

+-------------+--------------+
| cust_name   | cust_contact |
+-------------+--------------+
| Coyote Inc. | Y.Lee        |
+-------------+--------------+
1 row in set (0.05 sec)

在這個例子中,WHERE子句使用SOUNDEX()函數來轉換cust_contact列值和搜索串為它們的SOUNDEX值。因為Y.Lee和Y.lie發音相似,所以它們的SOUNDEX值匹配,因此WHERE子句正確地過濾了所需的數據。

9.2.3 日期和時間處理函數

日期和時間採用相應的數據類型和特殊的格式存儲,以便快速和有效地排序或過濾,並節省物理存儲空間。

一般,應用程式不使用來存儲日期和時間的格式,因此日期和時間函數總是被用來讀取、統計和處理這些值。所以,日期和時間函數在MySQL語言中很重要。

表格轉載:菜鳥教程

函數 說明 演示
ADDDATE(d,n) 計算起始日期 d 加上 n 天的日期 SELECT ADDDATE("2020-01-15", 3);
SELECT ADDDATE("2020-01-15", INTERVAL 3 DAY);
->(2020-01-18)
ADDTIME(t,n) 時間 t 加上 n 秒的時間 SELECT ADDTIME('2011-11-11 11:11:11', 5);
->2011-11-11 11:11:16 (秒)
CURDATE() 返回當前日期 SELECT CURDATE();
->2020-01-15
CURTIME() 返回當前時間 SELECT CURTIME();
->16:41:01
DATE() 從日期或日期時間表達式中提取日期值 SELECT DATE("2020-01-15");
->2020-01-15
DATEDIFF(d1,d2) 計算日期 d1->d2 之間相隔的天數 SELECT DATEDIFF("2020-01-15","2020-01-4");
->11(前面的日期減去後面的日期)
DATE_ADD(d,INTERVAL expr type) 計算起始日期 d 加上一個時間段後的日期 SELECT ADDDATE('2011-11-11 11:11:11',1);
-> 2011-11-12 11:11:11 (預設是天)
SELECT ADDDATE('2011-11-11 11:11:11', INTERVAL 5 MINUTE);
-> 2011-11-11 11:16:11 (TYPE的取值與上面那個列出來的函數類似)
DATE_FORMAT(d,f) 按表達式 f的要求顯示日期 d SELECT DATE_FORMAT('2011-11-11 11:11:11','%Y-%m-%d %r')
-> 2011-11-11 11:11:11 AM
DAY(d) 返回日期值 d 的日期部分 SELECT DAY("2020-01-15");
-> 15
DAYOFWEEK(d) 日期 d 今天是星期幾,1 星期日,2 星期一,以此類推 SELECT DAYOFWEEK("2020-01-15");
-> 4
HOUR(t) 返回 t 中的小時值 SELECT HOUR("2020-01-15 17:21");
-> 17
MINUTE(t) 返回 t 中的分鐘值 SELECT MINUTE("2020-01-15 17:21");
-> 21
MONTH(d) 返回日期d中的月份值,1 到 12 SELECT MONTH("2020-01-15 17:21");
-> 1
NOW() 返回當前日期和時間 SELECT NOW();
-> 2020-01-15 17:24:18
MICROSECOND(date) 返回日期參數所對應的微秒數 SELECT MICROSECOND("2017-06-20 09:34:00.000023");
-> -> 23
TIME(expression) 提取傳入表達式的時間部分 SELECT TIME("19:30:10");
-> 19:30:10
YEAR(t) 返回t日期中的年份 SELECT YEAR("2020-01-15 17:21");
-> 2020

更多參考:菜鳥教程

需要註意的是MySQL使用的日期格式。無論是什麼時候指定一個日期,或是插入或更新等,日期必須為格式yyyy-mm-dd。所以,2020年1月15號,給出的是2020-01-15.雖然其他的日期格式可能也行,但這是首選的日期格式,因為它排除了多義性(如,04/05/06是2006年5月4號還是2006年4月5號或...)。

應該總是使用4位數字的年份。MySQL雖然支持2位數字的年份,比如處理00-69位2000-2069。雖然它們可能是打算要的年份,但使用完整的4位數字年份更可靠。

在資料庫表中檢索時間日期,比如:

SELECT cust_id, order_num
FROM orders
WHERE order_date = '2005-09-01';

這樣寫的 order_date = '2005-09-01' 可靠嗎?如果order_date的數據類型是datetime,這種類型存儲日期及時間值,那麼在例表中的值全都具有時間值00:00:00,但實際上很可能並不總是這樣。如果用當前日期和時間存儲訂單日期(因此我們得知道訂單日期和下訂單當前的時間),怎麼辦??比如,存儲的order_date值為2005-09-01 11:30:05,則WHERE order_date = '2005-09-01'就失敗。

解決的方式:讓MySQL僅將給出的日期與列中的日期部分進行比較,而不是將給出的日期與整個列值進行比較。所以得使用DATE()函數。DATE(order_date)表示MySQL僅提取列的日期部分,所以修改如下:

SELECT cust_id, order_num
FROM orders
WHERE DATE(order_date) = '2005-09-01';

所以,對於日期的數據要特別註意,如果要的是日期,使用DATE(),如果要的是天,使用DAY(),如果要的是月,使用MONTH()等。最好明確要的是什麼格式的日期,即使知道相應的列只包含日期也應該加上函數。

還有一種日期比較需要說明。如果要檢索2005年9月下的所有訂單,怎麼辦??簡單的相等測試肯定不行,因為它也要匹配月份中的天數。提供以下的解決方法:

SELECT cust_id, order_num
FROM orders
WHERE DATE(order_date) BETWEEN '2005-09-01' AND '2005-09-30';

其中,BETWEEN操作符用來把2005-09-01和2005-09-30定義為一個要匹配的日期範圍。
還有另一種:

SELECT cust_id, order_num
FROM orders
WHERE YEAR(order_date) = 2005 AND MONTH(order_date) = 9;

解釋:YEAR()是一個從日期(或日期時間)中返回年份的函數。類似,MONTH從日期中返回月份。因此WHERE YEAR(order_date) = 2005 AND MONTH(order_date) = 9檢索出order_date為2005年9月的所有行。

9.2.3 數值處理函數

數值處理函數僅處理數值數據。一般主要用於代數、三角或幾何運算。

在主要DBMS的函數中,數值函數是最統一最一致的函數。

函數 說明
ABS(t) 返回數t的絕對值
COS(t) 返回角度為t的餘弦
EXP(t) 返回數t的指數值
MOD(a, b) 返回除操作(a/b)的餘數 = (a%b)
PI() 返回圓周率
RAND() 返回一個隨機數
SIN(t) 返回角度為t的正弦
SQRT(t) 返回數t的平方根
TAN(t) 返回角度為t的正切

小結:介紹瞭如何使用SQL的數據處理函數,主要註意日期函數的使用。這些函數不需要死記硬背,忘了就拿出來看。當然,最好簡單的函數就記一記,比如:ABS()、SQRT()、YEAR()、HOUR()、DAY()等這些。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Linux伺服器下運行同時包含CPU和GPU版本TensorFlow的項目,對於GPU版本,首先使用Anaconda建立GPU環境,首先將本地環境同步到服務上,再卸載cpu版本的pytorch和TensorFlow,下載GPU版對應版本的pytorch和TensorFlow。執行不同版本項目時,只需... ...
  • Centos下PHP,Apache,Mysql 的安裝 安裝Apache yum -y install httpd systemctl start httpd 添加防火牆 firewall-cmd --permanent --add-port=80/tcp systemctl restart fir ...
  • 隨著業務的越發複雜,對軟體系統的要求越來越高,這意味著我們需要隨時掌控系統的運行情況。因此,對系統的實時監控以及可視化展示,就成了基礎架構的必須能力。 Grafana官方網站 Grafana介紹 Grafana是一個跨平臺的開源的度量分析和可視化工具,可以通過將採集的數據查詢然後可視化的展示,並及時 ...
  • 10.3 彙總數據 我們經常需要彙總數據而不用把它們實際檢索處出來,為此MySQL提供了專門的函數。使用這些函數,MySQL查詢可用於檢索數據,以便分析和報表的生成。這種類型的檢索例子有以下幾種: 確定表中的行數(或者滿足某個條件或包含某個特定值的行數)。 獲得表中行組的和。 找出表列(或所有行或某 ...
  • 一次偶然的機會,發現在登陸驗證時,改變用戶名的大小寫,同樣可以登錄成功,這是由於,當時使用的mysql資料庫對大小寫不敏感,查詢時總是能查詢到數據。一番查找資料,給出的原因是:在創建資料庫的時候,選擇了utf8_general_ci排序規則。 創建資料庫時,需要同時選擇字元集和排序規則,字元集大家都 ...
  • 發現一段經典SQL,不用迴圈游標,一句update代碼實現滾動計算結存。為方便理解,結合實例測試之 --1,源數據#t1,jcshl初值為每個sid的當前庫存數量,要實現的效果:每個sid的後一結存數量為前一jcshl結存數量-chkshl出庫數量 SELECT * FROM #t1 ORDER B ...
  • 1、 查看電腦名use master go select @@servername select serverproperty('servername') 2、同步更新SQLserverif serverproperty('servername') <> @@servername begin de ...
  • Linux平臺環境下主要有兩種連接方式,一種是TCP/IP連接方式,另一種就是socket連接。 在Windows平臺下,有name pipe和share memory(不考慮)兩種。 TCP/IP連接是網路中用得最多的一種方式。 環境: MySQL資料庫實例IP:192.168.0.2 MySQL ...
一周排行
    -Advertisement-
    Play Games
  • JWT(JSON Web Token)是一種用於在網路應用之間傳遞信息的開放標準(RFC 7519)。它使用 JSON 對象在安全可靠的方式下傳遞信息,通常用於身份驗證和信息交換。 在Web API中,JWT通常用於對用戶進行身份驗證和授權。當用戶登錄成功後,伺服器會生成一個Token並返回給客戶端 ...
  • 老周在幾個世紀前曾寫過樹莓派相關的 iOT 水文,之所以沒寫 Nano Framework 相關的內容,是因為那時候這貨還不成熟,可玩性不高。不過,這貨現在已經相對完善,老周都把它用在項目上了——第一個是自製的智能插座,這個某寶上50多塊可以買到,搜“esp32 插座”就能找到。一種是 86 型盒子 ...
  • 引言 上一篇我們創建了一個Sample.Api項目和Sample.Repository,並且帶大家熟悉了一下Moq的概念,這一章我們來實戰一下在xUnit項目使用依賴註入。 Xunit.DependencyInjection Xunit.DependencyInjection 是一個用於 xUnit ...
  • 在 Avalonia 中,樣式是定義控制項外觀的一種方式,而控制項主題則是一組樣式和資源,用於定義應用程式的整體外觀和感覺。本文將深入探討這些概念,並提供示例代碼以幫助您更好地理解它們。 樣式是什麼? 樣式是一組屬性,用於定義控制項的外觀。它們可以包括背景色、邊框、字體樣式等。在 Avalonia 中,樣 ...
  • 在處理大型Excel工作簿時,有時候我們需要在工作表中凍結窗格,這樣可以在滾動查看數據的同時保持某些行或列固定不動。凍結窗格可以幫助我們更容易地導航和理解複雜的數據集。相反,當你不需要凍結窗格時,你可能需要解凍它們以獲得完整的視野。 下麵將介紹如何使用免費.NET庫通過C#實現凍結Excel視窗以鎖 ...
  • .NET 部署 IIS 的簡單步驟一: 下載 dotnet-hosting-x.y.z-win.exe ,下載地址:.NET Downloads (Linux, macOS, and Windows) (microsoft.com) .NET 部署 IIS 的簡單步驟二: 選擇對應的版本,點擊進入詳 ...
  • 拓展閱讀 資料庫設計工具-08-概覽 資料庫設計工具-08-powerdesigner 資料庫設計工具-09-mysql workbench 資料庫設計工具-10-dbdesign 資料庫設計工具-11-dbeaver 資料庫設計工具-12-pgmodeler 資料庫設計工具-13-erdplus ...
  • 初識STL STL,(Standard Template Library),即"標準模板庫",由惠普實驗室開發,STL中提供了非常多對信息學奧賽很有用的東西。 vector vetor是STL中的一個容器,可以看作一個不定長的數組,其基本形式為: vector<數據類型> 名字; 如: vector ...
  • 前言 最近自己做了個 Falsk 小項目,在部署上伺服器的時候,發現雖然不乏相關教程,但大多都是將自己項目代碼複製出來,不講核心邏輯,不太簡潔,於是將自己部署的經驗寫成內容分享出來。 uWSGI 簡介 uWSGI: 一種實現了多種協議(包括 uwsgi、http)並能提供伺服器搭建功能的 Pytho ...
  • 1 文本Embedding 將整個文本轉化為實數向量的技術。 Embedding優點是可將離散的詞語或句子轉化為連續的向量,就可用數學方法來處理詞語或句子,捕捉到文本的語義信息,文本和文本的關係信息。 ◉ 優質的Embedding通常會讓語義相似的文本在空間中彼此接近 ◉ 優質的Embedding相 ...