目錄
簡單檢索數據
- 簡單查詢
--檢索多列
SELECT 列名1,列名2,列名3 FROM 表名;
--檢索所有列
SELECT * FROM 表名;
注意:多條SQL語句必須以分號(;)分隔;SQL語句不區分大小寫,因此 SELECT與select是相同的。但爲了使代碼更易於閱讀和調試,習慣將所有SQL關鍵字使用大寫,而對所有列和表名使用小寫。
- 檢索不同的行
SELECT返回所有匹配的行,使用DISTINCT關鍵字來指示MySQL 只返回不同的值。
注意:DISTINCT關鍵字必須直接放在列名的前面,並且應用於所有列而不僅是前置它的列。
SELECT DISTINCT 列名 FROM 表名;
- 限制結果
SELECT語句返回所有匹配的行,如果只想返回第一行或前幾行,可使用LIMIT子句。
--LIMIT 5指示MySQL返回不多於5行
SELECT 列名 FROM 表名 limit 5;
--LIMIT 5, 5指示MySQL返回從行5開始的5行
--注意:檢索出來的第一行爲行0而不是行1
SELECT 列名 FROM 表名 limit 5,5;
排序檢索數據
- 排序數據
爲了明確地對SELECT語句檢索出的數據進行排序,可使用ORDER BY子句,默認升序排序。
注意:通常,ORDER BY子句中使用的列將是爲顯示所選擇的列。但是,實際上並不一定要這樣,用非檢索的列排序數據是完全合法的。
--按一個列排序
SELECT 列名 FROM 表名 ORDER BY 列名;
--按多個列排序
SELECT 列名 FROM 表名 ORDER BY 列名1,列名2,列名3;
- 指定排序方向
默認排序方向爲升序(ASC關鍵字),如果想進行降序排序, 就必須指定DESC關鍵字。
注意:DESC關鍵字只應用到直接位於其前面的列名。
SELECT 列名 FROM 表名 ORDER BY 列名 DESC;
--按一個列降序,一個列升序
SELECT 列名 FROM 表名 ORDER BY 列名1 DESC,列名2;
使用ORDER BY和LIMIT的組合,能夠找出一個列中的最大或最小值。
SELECT 列名 FROM 表名 ORDER BY 列名 LIMIT 1;
數據過濾
過濾數據
- 使用 WHERE 子句
在SELECT 語句中,數據根據 WHERE 子句中指定的搜索條件進行過濾。
注意:在同時使用ORDER BY和WHERE子句時,應該讓ORDER BY位於WHERE之後,否則將會產生錯誤。
SELECT 列名 FROM 表名 WHERE 條件;
- WHERE 子句操作符
-- <> 和 != 均是不匹配檢查
SELECT vend_id, prod_name FROM products WHERE vend_id <> 1003;
-- 如果將值與串類型的列進行比較,則需要限定引號
SELECT vend_id, prod_name FROM products WHERE prod_name = 'fuses';
-- 範圍值檢查
SELECT prod_name, prod_price FROM products WHERE prod_price BETWEEN 5 AND 10;
-- 空值檢查
SELECT prod_name FROM products WHERE prod_price IS NULL;
- AND 和 OR 操作符
AND 和 OR 用來連接WHERE子句中的多個條件,注意 AND 的優先級比 OR 高,任何時候使用具有AND和OR操作符的WHERE子句,都應該使用圓括號明確地分組操作符,而不要過分依賴默認計算次序。
- IN 操作符
IN操作符用來指定條件範圍,範圍中的每個條件都可以進行匹配(等同於OR)。IN取合法值的由逗號分隔的清單,全都括在圓括號中。
SELECT prod_name, prod_price FROM products WHERE vend_id IN (1002,1003) ORDER BY prod_name;
- NOT 操作符
WHERE子句中的NOT操作符用來否定它之後所跟的任何條件。
注意:MySQL支持使用NOT對IN、BETWEEN和 EXISTS子句取反,這與多數其他DBMS允許使用NOT對各種條件取反有很大的差別。
SELECT prod_name, prod_price FROM products WHERE vend_id NOT IN (1002,1003) ORDER BY prod_name;
用通配符進行過濾
- LIKE 操作符
如果在搜索子句中使用通配符,那麼必須使用 LIKE 操作符。LIKE 會指示MySQL,後跟的搜索模式利用通配符匹配而不是直接相等匹配進行比較。主要有兩種通配符:
- 百分號(%):任何字符出現任意次數;特別注意%不能匹配NULL;
- 下劃線(_):只匹配單個任意字符。
- 使用通配符技巧
- 不要過度使用通配符,能不用就不用;
- 在確實需要使用通配符時,最好不要將通配符用在搜索模式開始處;
- 仔細注意通配符位置。如果放錯地方,可能不會返回想要的數據。
用正則表達式進行搜索
- 基本字符匹配
MYSQL用WHERE子句對正則表達式提供了初步的支持,允許你指定正則表達式,過濾SELECT檢索出的數據。REGEXP關鍵字告訴MySQL它後面所跟的東西作爲正則表達式。
注意:LIKE和REGEXP的不同在於,LIKE匹配整個串而REGEXP匹配子串。
--檢索列prod_name包含文本1000的所有行
SELECT prod_name FROM products WHERE prod_name REGEXP '1000' ORDER BY prod_name;
- 進行OR匹配
爲搜索兩個串之一,使用 | 。使用 | 從功能上類似於在SELECT語句中使用OR語句,多個OR條件可併入單個正則表達式。
SELECT prod_name FROM products WHERE prod_name REGEXP '1000|2000|3000' ORDER BY prod_name;
- 匹配幾個字符之一
通過指定一組用 [ 和 ] 括起來的字符來匹配特定的字符
--[123]意思是匹配1或2或3
SELECT prod_name FROM products WHERE prod_name REGEXP '[123] Ton' ORDER BY prod_name;
注意 | 和 [ ]兩者的聯繫:正則表達式 [123]Ton其實是 [1|2|3]Ton 的縮寫。正則表達式‘1|2|3 Ton’的意思是‘1’或‘2’或‘3 ton’,需要區分於 ‘[1|2|3] Ton’。
字符集合也可以被否定,即,它們將匹配除指定字符外的任何東西。比如[^123]匹配除這些字符外的任何東西。
- 匹配範圍
正則表達式 '[0-9]' 跟 ‘[0123456789]’ 一樣,會匹配數字0到9。另外,[a-z]匹配任意字母字符。
- 匹配特殊字符
爲了匹配特殊字符,必須用 \\ 爲前導,比如\\- 表示 -,\\. 表示。
- 匹配字符類
- 匹配多個實例
- 定位符
創建計算字段
計算字段是運行時在SELECT語句內創建的,它實際並不存在於數據庫表中。
- 拼接字段
假設有一張vendors表包含供應商名和位置信息,我們需要要生成一個供應商報表,在供應商的名字中按照name(location)這樣的格式列出供應商的位置。解決辦法是把兩個列拼接起來,用Concat()函數來拼接兩個列,拼接的列用AS指定別名。
SELECT Concat(vend_name, '(', vend_country, ')')AS vend_title FROM vendors ORDER BY vend_name;
- 執行算術計算
計算字段的另一常見用途是對檢索出的數據進行算術計算。
SELECT prod_id, quantity, item_price, quantity*item_price AS expanded price FROM orderitems WHERE order_num = 20005;
使用數據處理函數
- 文本處理函數
--WHERE子句使用Soundex()函數來轉換cust_ contact列值和搜索串爲它們的SOUNDEX值
--會匹配所有發音類似於Y.Lie的聯繫名
SELECT cust_name, cust_contact FROM customers WHERE Soudex(cust_contact) = Soudex( 'Y.Lie');
- 日期和時間處理函數
--Date(order_date)指示MySQL僅提取列的日期部分
SELECT cust_id, order_num FROM orders WHERE Date(order_date) = '2005-09-01';
--檢索出年份爲2005和月份爲9的日期
SELECT cust_id, order_num FROM orders WHERE Year(order_date) = 2005 and Month(order_date) = 9;
- 數值處理函數
彙總數據
- 聚集函數
count()有兩種用法,一種是使用COUNT(*)對錶中行的數目進行計數,不管表列中包含的是空值(NULL)還是非空值;另一種是和其它函數一樣,count(column)對指定列計數,忽略null值。
- 聚集不同值
對聚集函數都可以指定DISTINCT參數,從而只對不同的值進行彙總。注意:不允許使用COUNT(DISTINCT),只能在指定列名的情況下使用。
--計算不同產品的平均價格
SELECT AVG(DISTINCT prod_price) AS avg_price FROM products WHERE vend_id = 1003;
- 組合聚集函數
SELECT語句可根據需要包含多個聚集函數
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;
分組數據
分組允許把數據分爲多個邏輯組,以便能對每個組進行聚集計算。
- Group by 子句
--GROUP BY子句指示MySQL分組數據,然後對每個組而不是整個結果集進行聚集。
SELECT vend_id, COUNT(*) AS num_prods FROM products GROUP BY vend_id;
使用Group by 子句的規定:
- group by子句可以包含任意數目的列;
- group by子句列出每個列都必須是檢索列或有效表達式(但不能是聚集函數);
- 除聚集計算語句外,SELECT語句中的每個列都必須在GROUP BY子句中給出;
-
如果分組列中具有NULL值,則NULL將作爲一個分組返回;
-
GROUP BY子句必須出現在WHERE子句之後,ORDER BY子句之前。
注意:一般在使用GROUP BY子句時,應該也給出ORDER BY子句,這是保證數據正確排序的唯一方法
- Having子句
HAVING非常類似於WHERE,兩者唯一的差別是WHERE過濾行,而HAVING過濾分組。WHERE在數據分組前進行過濾,HAVING在數據分組後進行過濾。
SELECT vend_id, COUNT(*) AS num_prods FROM products WHERE prod_price >= 10 GROUP BY vend_id HAVING COUNT(*) >= 2;
SELECT子句順序總結:SELECT、FROM、WHERE、GROUP BY、HAVING、ORDER BY、LIMIT
使用子查詢
- 利用子查詢進行過濾
--子查詢一般與IN操作符結合使用
select cust_name, cust_contact from customers where cust_id in(
select cust_id from orders where order_num in(
select order_num from orderitems where prod_id = 'TNT2'));
- 作爲計算字段使用子查詢
--顯示customers表中每個客戶的訂單總數
select cust_name, cust_state, (select count(*) from orders where orders.id = customers.cust_id) as orders from customers order by cust_name;
聯結表
- 內部聯結
內部聯結又稱爲等值聯結,將兩個表中存在聯結關係的字段符合聯結關係的那些記錄形成記錄集的聯結。有兩種語法,建議使用第二種,使用明確的聯結語法能夠確保不會忘記聯結條件,有時候這樣做也能影響性能。需要注意的一點是,使用INNER JOIN聯結時,聯結條件用特定的ON子句而不是WHERE 子句給出。由沒有聯結條件的表關係返回的結果爲笛卡兒積。
SELECT vend_name, prod_name, prod_price FROM vendors, products WHERE vendors.vend_id = products.vend_id ORDER BY vend_name, prod_name;
--用inner join明確聯結類型
SELECT vend_name, prod_name, prod_price FROM vendors INNER JOIN products ON vendors.vend_id = products.vend_id ORDER BY vend_name, prod_name;
- 外部聯結
外部聯結中包含了在相關表中沒有關聯的行。用LEFT/RIGHT OUTER JOIN 指定表之間的關係,用ON子句指定聯結條件。
組合查詢
可用UNION操作符來組合數條SQL查詢。利用UNION,可給出多條SELECT語句,將它們的結果組合成單個結果集。
select vend_id, prod_id, prod_price from products where prod_price <= 5
union
select vend_id, prod_id, prod_price from products where vend_id in (1001,1002);
UNION使用規則:
- UNION必須由兩條或兩條以上的SELECT語句組成,語句之間用關鍵字UNION分隔;
- UNION中的每個查詢必須包含相同的列、表達式或聚集函數(順序不要求相同);
- 列數據類型必須兼容:類型不必完全相同,但必須是DBMS可以隱含地轉換的類型;
注意:UNION會從查詢結果集中自動去除重複的行(換句話說,它的行爲與單條SELECT語句中使用多個WHERE子句條件一樣),如果想返回所有匹配行,可使用UNION ALL。另外,在用UNION組合查詢時,只能使用一條ORDER BY子句,它必須出現在最後一條SELECT語句之後。
全文本搜索
在使用全文本搜索時,MySQL不需要分別查看每個行,不需要分別分析和處理每個詞。MySQL創建指定列中各詞的一個索引,搜索可以針對這些詞進行。
- 啓用全文本搜索支持
一般在創建表時啓用全文本搜索。CREATE TABLE語句接受FULLTEXT子句(不要在導入數據時使用FULLTEXT,應該首先導入所有數據,然後再修改表,定義FULLTEXT),它給出被索引列的一個逗號分隔的列表。如圖所示,創建表時,MySQL會根據子句FULLTEXT(note_text)的指示對它進行索引,在定義之後,MySQL會自動維護該索引。
需要注意的一點是,兩個最常使用的引擎爲MyISAM和InnoDB,MyISAM支持全文本搜索,而InnoDB不支持。
- 進行全文本搜索
在索引之後,使用兩個函數Match()和Against()執行全文本搜索,其中Match()指定被搜索的列,Against()指定要使用的搜索表達式
select note_text from productnotes where Match(note_text) Against('rabbit');
注意:傳遞給 Match() 的值必須與FULLTEXT()定義中的相同。如果指定多個列,則必須列出它們(而且次序正確)。另外,全文本搜索不區分大小寫。
SELECT note_text FROM productnotes WHERE note_text LIKE '%rabbit%';
上面兩條select語句的作用相同,但結果的次序不同。全文本搜索的一個重要部分就是對結果排序,具有較高等級的行先返回。
- 使用查詢擴展
查詢擴展用來設法放寬所返回的全文本搜索結果的範圍,查詢結果按照等級從高到低依次排序。
select note_text from productnotes where Match(note_text) Against('anvils' with query expansion);
- 布爾文本搜索
--匹配包含heavy但不包含任意以rope開始詞的行
select note_text from productnotes where Match(note_text) Against('heavy -rope*' in boolenan mode);