MySQL必知必會—概念篇mysql
# 檢索單個列,例如從 products 表中檢索一個名爲 prod_name 的列。
SELECT prod_name FROM products;
# 檢索多個列。注意,列名之間要用逗號分隔,最後一個列名後不要加逗號,會報錯。
SELECT prod_id, prod_name, prod_price FROM products;
# 檢索全部列。
SELECT * FROM products;
# 只檢索出不一樣的行, DESTINCT 關鍵字可讓指令只返回不一樣的值。若是指令,products 表中可能一共有14行,如今只返回不一樣(惟一)的 vend_id 行,可能就只返回4行了。
SELECT DISTINCT vend_id FROM products;
# 限制結果, LIMIT 5 表示只返回很少於5行。
SELECT prod_name FROM products LIMIT 5;
# LIMIT 5, 5 表示返回從行5開始的5行。
SELECT prod_name FROM products LIMIT 5, 5;
# 或者使用 LIMIT 5 OFFSET 5, 跟上面結果相同。
SELECT prod_name FROM products LIMIT 5 OFFSET 5;
# 注意,返回行數是從 0 開始的。因此,LIMIT 1, 1 將檢索出第二行,而不是第一行。
SELECT prod_name FROM products LIMIT 1,1;
複製代碼
不使用排序時,其實檢索出的數據並非以純粹的隨機順序顯示的,數據通常將以它在底層表中出現的順序顯示。這能夠是數據最初添加到表中的順序,可是,若是數據後來進行過更新或者刪除,則此順序將會受到 MySQL 重用回收存儲空間的影響。所以,若是不明確控制的話,不能(也不該該)依賴該排序順序。github
關係數據庫設計理論認爲:若是不明確規定排序順序,則不該該假定檢索出的數據的順序有意義。正則表達式
ORDER BY 子句,能夠給 SELECT 語句檢索出來的數據進行排序。 ORDER BY 子句取一個或多個列的名字。據此對輸出進行排序。算法
# 沒有排序
SELECT prod_name FROM products;
# 對 prod_name 列以字母順序排序數據
SELECT prod_name FROM products ORDER BY prod_name;
# 按多個列排序:以下會先按照 prod_price 排序,
# 只有出現相同的 prod_price 時,纔會再按照 prod_name 排序。
SELECT prod_id, prod_price, prod_name FROM products ORDER BY prod_price, prod_name;
# 指定排序方向,默認是升序,例如按照 prod_price 降序排序(最貴的排在最前面)
SELECT prod_id, prod_price, prod_name FROM products ORDER BY prod_price DESC;
# 多個列排序,例如按照 prod_price 降序,最貴的在最前面,而後在對產品名排序
SELECT prod_id, prod_price, prod_name FROM products ORDER BY prod_price DESC, prod_name;
# ORDER BY 和 LIMIT 搭配,能夠找出一個列中最高或最低的值。
SELECT prod_price FROM products ORDER BY prod_price DESC LIMIT 1;
複製代碼
數據庫包含大量的數據,可是咱們不多須要檢索表中全部的行。只檢索所需數據須要指定過濾條件,在 SELECT 語句中,數據根據 WHERE 子句中指定的搜索條件進行過濾。sql
# 檢索 pro_price 爲 2.50 的行
SELECT prod_name FROM products WHERE prod_price = 2.50;
# 執行篩選匹配時默認不區分大小寫,因此 fuses 能夠檢索出 Fuses
SELECT prod_name, prod_price FROM products WHERE prod_name = 'fuses';
# 輸出
+-----------+------------+
| prod_name | prod_price |
+-----------+------------+
| Fuses | 3.42 |
+-----------+------------+
# 檢索出 vend_id 不等於 1003 的行
SELECT vend_id, prod_name FROM products WHERE vend_id <> 1003;
# 檢索 prod_price 在 5 到 10 之間的全部行
SELECT prod_name, prod_price FROM products WHERE prod_price BETWEEN 5 AND 10;
# 檢查具備 NULL 值的列,用 IS NULL 子句
SELECT cust_id FROM customers WHERE cust_email IS NULL;
複製代碼
操做符 | 說明 |
---|---|
= | 等於 |
<> | 不等於 |
!= | 不等於 |
< | 小於 |
<= | 小於等於 |
> | 大於 |
>= | 大於等於 |
BETWEEN | 在指定的兩個值之間 |
MySQL 容許組合多個 WHERE 子句。這些子句分爲兩種方式使用:以 AND 子句的方式或 OR 子句的方式使用。數據庫
### AND 操做符
# 檢索出 vend_id 等於 1003 而且 prod_price 小於等於 10 的行
SELECT prod_price, prod_name FROM products WHERE vend_id = 1003 AND prod_price <= 10;
#### OR 操做符
# 檢索出 vend_id 等於 1002 或 vend_id 等於 1003 的全部行
SELECT prod_name, prod_price FROM products WHERE vend_id = 1002 OR vend_id = 1003;
# AND 和 OR 合用,AND 優先級高。
# 下面檢索出的結果是 vend_id 是 1003 而且 prod_price 大於等於 10 的和全部 vend_id 是 1002 的行。
SELECT vend_id, prod_name, prod_price FROM products WHERE vend_id = 1002 OR vend_id = 1003 AND prod_price >= 10;
# 輸出結果
+---------+----------------+------------+
| vend_id | prod_name | prod_price |
+---------+----------------+------------+
| 1002 | Fuses | 3.42 |
| 1002 | Oil can | 8.99 |
| 1003 | Detonator | 13.00 |
| 1003 | Bird seed | 10.00 |
| 1003 | Safe | 50.00 |
| 1003 | TNT (5 sticks) | 10.00 |
+---------+----------------+------------+
# 若是想檢索出 vend_id 是 1003 而且 prod_price 大於等於 10 的和 vend_id 是 1002 而且 prod_price 大於等於 10 的行,須要加括號。
SELECT vend_id, prod_name, prod_price FROM products WHERE (vend_id = 1002 OR vend_id = 1003) AND prod_price >= 10;
### IN 操做符,指定條件範圍,範圍中的每一個條件均可以進行匹配。IN 取值是所有括在圓括號中的由逗號分隔的列表。
SELECT vend_id, prod_name, prod_price FROM products WHERE vend_id IN (1002, 1003);
### NOT 操做符,否認它以後的任何條件
SELECT vend_id, prod_name, prod_price FROM products WHERE vend_id NOT IN (1002, 1003);
複製代碼
%
表示任何字符出現任意次數,可使0次,1次,n次數組
### 找出全部以 jet 開頭的產品
SELECT prod_id, prod_name FROM products WHERE prod_name LIKE 'jet%';
+---------+--------------+
| prod_id | prod_name |
+---------+--------------+
| JP1000 | JetPack 1000 |
| JP2000 | JetPack 2000 |
+---------+--------------+
### 通配符可在搜索模式中任意位置使用,而且可使用多個通配符。
SELECT prod_id, prod_name FROM products WHERE prod_name LIKE '%anvil%';
+---------+--------------+
| prod_id | prod_name |
+---------+--------------+
| ANV01 | .5 ton anvil |
| ANV02 | 1 ton anvil |
| ANV03 | 2 ton anvil |
+---------+--------------+
複製代碼
下劃線 _ 只能匹配單個字符,只能匹配一個,不能多也不能少。數據庫設計
### 對比一下下面兩個通配符結果
SELECT prod_id, prod_name FROM products WHERE prod_name LIKE '_ ton anvil';
+---------+-------------+
| prod_id | prod_name |
+---------+-------------+
| ANV02 | 1 ton anvil |
| ANV03 | 2 ton anvil |
+---------+-------------+
SELECT prod_id, prod_name FROM products WHERE prod_name LIKE '% ton anvil';
+---------+--------------+
| prod_id | prod_name |
+---------+--------------+
| ANV01 | .5 ton anvil |
| ANV02 | 1 ton anvil |
| ANV03 | 2 ton anvil |
+---------+--------------+
### 下劃線通配符比百分號通配符少了一個 .5 的數據
複製代碼
### 基本字符匹配,下面的語句檢索列 prod_name 包含文本 1000 的全部行。
SELECT prod_name FROM products WHERE prod_name REGEXP '1000' ORDER BY prod_name;
### 區分大小寫須要用到 BINARY 關鍵字
SELECT prod_name FROM products WHERE prod_name REGEXP BINARY 'S';
### 使用 | 進行 OR 匹配,能夠有兩個以上的 OR 條件,例如: '1000|2000|3000'
SELECT prod_name FROM products WHERE prod_name REGEXP '1000|2000';
+--------------+
| prod_name |
+--------------+
| JetPack 1000 |
| JetPack 2000 |
+--------------+
### 匹配幾個字符之一
SELECT prod_name FROM products WHERE prod_name REGEXP '[1,2,3] Ton' ORDER BY prod_name;
+-------------+
| prod_name |
+-------------+
| 1 ton anvil |
| 2 ton anvil |
+-------------+
### 注意區別 1|2|3 Ton,這表示匹配出 1,2和3 Ton,其實[123]是[1|2|3]的縮寫
SELECT prod_name FROM products WHERE prod_name REGEXP '1|2|3 Ton' ORDER BY prod_name;
+---------------+
| prod_name |
+---------------+
| 1 ton anvil |
| 2 ton anvil |
| JetPack 1000 |
| JetPack 2000 |
| TNT (1 stick) |
+---------------+
### 匹配特殊字符, \\ 來轉義特殊字符
SELECT vend_name FROM vendors WHERE vend_name REGEXP '\\.' ORDER BY vend_name;
+--------------+
| vend_name |
+--------------+
| Furball Inc. |
+--------------+
### 匹配出連在一塊兒的4個數字
SELECT prod_name FROM products WHERE prod_name REGEXP '[:digit:]{4}' ORDER BY prod_name;
+--------------+
| prod_name |
+--------------+
| JetPack 1000 |
| JetPack 2000 |
+--------------+
複製代碼
元字符 | 說明 |
---|---|
\f | 換頁 |
\n | 換行 |
\r | 回車 |
\t | 製表 |
\v | 縱向製表 |
\\ | 反斜槓 |
^ | 文本的開始 |
$ | 文本的結束 |
[[:<:]](8版本以後改成 \b) | 詞的開始 |
[[:>:]](8版本以後改成 \b) | 詞的結束 |
多數正則表達式實現使用單個反斜槓轉義特殊字符,以便能使用這些字符自己。但 MySQL 要求兩個反斜槓(MySQL本身解釋一個,正則表達式庫解釋另外一個)。函數
類 | 說明 |
---|---|
[:alnum:] | 任意字符和數字(同 [a-zA-Z0-9]) |
[:alpha:] | 任意字符(同 [a-zA-Z]) |
[:blank:] | 空格和製表 (同 [\t]) |
[:cntrl:] | ASCII控制字符 (ASCII 0 到 31 和 127) |
[:digit:] | 任意數字 (同 [0-9]) |
[:xdigit:] | 任意十六進制數字(同 [a-fA-F0-9]) |
[:lower:] | 任意小寫字母 (同 [a-z]) |
[:upper:] | 任意大寫字母(同 [A-Z]) |
[:print:] | 任意可打印字符 |
[:graph:] | 與[:print:]相同,但不包含空格 |
[:punct:] | 既不在[:alnum:]又不在[:cntrl:]中的任意字符 |
[:space:] | 包括空格在內的任意空白字符(同 [\f\n\r\t\v]) |
在不使用數據庫表的狀況下用 SELECT 來測試正則表達式。 REGEXP 檢查老是返回0(沒有匹配)或 1(匹配)。
SELECT 'hello' REGEXP 'hello\\b';
+---------------------------+
| 'hello' REGEXP 'hello\\b' |
+---------------------------+
| 1 |
+---------------------------+
複製代碼
### 將查出來的名字和國家拼接出來展現,使用了 Concat、Trim函數,和 AS 關鍵字
SELECT Concat( Trim(vend_name), '(', Trim(vend_country), ')') AS vend_name FROM vendors ORDER BY vend_name;
+------------------------+
| vend_name |
+------------------------+
| ACME(USA) |
| Anvils R Us(USA) |
| Furball Inc.(USA) |
| Jet Set(England) |
| Jouets Et Ours(France) |
| LT Supplies(USA) |
+------------------------+
### 將20005訂單中的全部物品查出來,經過數量和單價算出總價
SELECT prod_id, quantity, item_price, quantity*item_price AS expanded_price FROM orderitems WHERE order_num = 20005;
+---------+----------+------------+----------------+
| prod_id | quantity | item_price | expanded_price |
+---------+----------+------------+----------------+
| ANV01 | 10 | 5.99 | 59.90 |
| ANV02 | 3 | 9.99 | 29.97 |
| TNT2 | 5 | 10.00 | 50.00 |
| FB | 1 | 10.00 | 10.00 |
+---------+----------+------------+----------------+
複製代碼
SELECT 提供了測試和實驗函數與計算的一個很好的方法,就是省略 FROM 子句
SELECT 3*2;
+-----+
| 3*2 |
+-----+
| 6 |
+-----+
SELECT Now();
+---------------------+
| Now() |
+---------------------+
| 2019-11-21 22:51:13 |
+---------------------+
複製代碼
函數沒有 SQL 的可移植性強,幾乎每種主要的 DBMS 的實現都支持其餘實現不支持的函數,有時差別還很大。爲了代碼的可移植性,不少人不同意使用特殊實現的功能,雖然這樣作頗有好處,可是對於應用程序的性能可能出現影響。若是決定使用函數,應該保證作好代碼註釋。
函 數 | 說 明 |
---|---|
Left() | 返回串左邊的字符 |
Length() | 返回串的長度 |
Locate() | 找出串的一個子串 |
Lower() | 將串轉換爲小寫 |
LTrim() | 去掉串左邊的空格 |
Right() | 返回串右邊的字符 |
RTrim() | 去掉串右邊的空格 |
Soundex() | 返回串的 SOUNDEX 值 |
SubString() | 返回子串的字符 |
Upper() | 將串轉換爲大寫 |
SOUNDEX 是一個將任何文本串轉換爲描述其語音表示的字母數字模式的算法。SOUNDEX 考慮了相似的發音字節和音節,使得能對串進行發音比較而不是字母比較。
### 例如用 Y. Lie 把 Y Lee 搜出來,由於它們發音相似
SELECT cust_name, cust_contact FROM customers WHERE Soundex(cust_contact) = Soundex('Y. Lie');
+-------------+--------------+
| cust_name | cust_contact |
+-------------+--------------+
| Coyote Inc. | Y Lee |
+-------------+--------------+
複製代碼
函 數 | 說 明 |
---|---|
AddDate() | 增長一個日期(天、周等) |
AddTime() | 增長一個時間(時、分等) |
CurDate() | 返回當前日期 |
CurTime() | 返回當前時間 |
Date() | 返回日期時間的日期部分 |
DateDiff() | 計算兩個日期之差 |
Date_Add() | 高度靈活的日期運算函數 |
Date_Format() | 返回一個格式化的日期或時間串 |
Year() | 返回一個日期的年份部分 |
Month() | 返回一個日期的月份部分 |
Day() | 返回一個日期的天數部分 |
DayOfWeek() | 對於一個日期,返回對應的星期幾 |
Hour() | 返回一個時間的小時部分 |
Minute() | 返回一個時間的分鐘部分 |
Second() | 返回一個時間的秒部分 |
Now() | 返回當前日期和時間 |
### 檢索出日期爲 2005-09-01 這天的訂單記錄
SELECT cust_id, order_num FROM orders WHERE order_date = '2005-09-01';
### 上面的檢索有個問題,若是 order_date 存儲的帶有時間,例如 2005-09-01 11:30:05 ,就檢索不到了,解決辦法是讓僅將給出的日期與列中的日期部分進行比較
SELECT cust_id, order_num FROM orders WHERE Date(order_date) = '2005-09-01';
### 若是想檢索出2005年9月的全部訂單
### 方法一,得記住每月有多少天,甚至要知道是否是閏年的2月
SELECT cust_id, order_num FROM orders WHERE Date(order_date) BETWEEN '2005-09-01' AND '2005-09-30';
### 方法二, 使用 Year() 和 Month() 函數
SELECT cust_id, order_num FROM orders WHERE Year(order_date) = 2005 AND Month(order_date) = 9;
複製代碼
函 數 | 說 明 |
---|---|
Abs() | 返回一個數的絕對值 |
Sin() | 返回一個角度的正弦 |
Cos() | 返回一個角度的餘弦 |
Tan() | 返回一個角度的正切 |
Exp() | 返回一個數的指數值 |
Mod() | 返回除操做的餘數 |
Pi() | 返回圓周率 |
Rand() | 返回一個隨機數 |
Sqrt() | 返回一個數的平方根 |
函 數 | 說 明 |
---|---|
AVG() | 返回某列的平均值 |
COUNT() | 返回某列的行數 |
MAX() | 返回某列的最大值 |
MIN() | 返回某列的最小值 |
SUM() | 返回某列值之和 |
### 計算出 products 表中全部產品的平均價格
SELECT AVG(prod_price) AS avg_price FROM products;
+-----------+
| avg_price |
+-----------+
| 16.133571 |
+-----------+
### 查看 customers 表中全部客戶的總數
SELECT COUNT(*) AS num_cust FROM customers;
+----------+
| num_cust |
+----------+
| 5 |
+----------+
### 只對具備電子郵件地址的客戶計數
SELECT COUNT(cust_email) AS num_cust FROM customers;
+----------+
| num_cust |
+----------+
| 3 |
+----------+
### 計算出訂單號爲 20005 的物品總數
SELECT SUM(quantity) AS items_ordered FROM orderitems WHERE order_num = 20005;
+---------------+
| items_ordered |
+---------------+
| 19 |
+---------------+
### 多個彙集函數組合
SELECT COUNT(*) AS num_items, MIN(prod_price) AS price_min, MAX(prod_price) AS price_max, AVG(prod_price) AS price_avg FROM products;
+-----------+-----------+-----------+-----------+
| num_items | price_min | price_max | price_avg |
+-----------+-----------+-----------+-----------+
| 14 | 2.50 | 55.00 | 16.133571 |
+-----------+-----------+-----------+-----------+
複製代碼
使用 DISTINCT 參數時,只會計算包含不一樣的值的行,若是指定參數爲 ALL 或者不指定參數,默認參數爲 ALL ,會計算全部的行。
### 看一下產品表裏有多少家供應商,由於有可能一家供應商提供不少產品。
### 所有的行
SELECT COUNT(vend_id) AS vend_count FROM products;
+------------+
| vend_count |
+------------+
| 14 |
+------------+
### 去重後就知道有 4 家供應商
SELECT COUNT(DISTINCT vend_id) AS vend_count FROM products;
+------------+
| vend_count |
+------------+
| 4 |
+------------+
複製代碼
SELECT vend_id, prod_price FROM products GROUP BY vend_id, prod_price;
複製代碼
### 列出至少有兩個訂單的全部顧客
SELECT cust_id, COUNT(*) AS orders FROM orders GROUP BY cust_id HAVING COUNT(*) >= 2;
### 列出具備2個(含)以上、價格爲10(含)以上的產品的供應商
SELECT vend_id, COUNT(*) AS num_prods FROM products WHERE prod_price >= 10 GROUP BY vend_id HAVING COUNT(*) >= 2;
### 列出總計訂單價格大於等於50的訂單,並按照總價排序
SELECT order_num, SUM(quantity*item_price) AS ordertotal FROM orderitems GROUP BY order_num HAVING SUM(quantity*item_price) >= 50 ORDER BY ordertotal;
+-----------+------------+
| order_num | ordertotal |
+-----------+------------+
| 20006 | 55.00 |
| 20008 | 125.00 |
| 20005 | 149.87 |
| 20007 | 1000.00 |
+-----------+------------+
複製代碼
SELECT > FROM > WHERE > GROUP BY > HAVING > ORDER BY > LIMIT
一個持續更新的github筆記,連接地址:Front-End-Basics,能夠watch,也能夠star。
此篇文章的地址:MySql必知必會