查詢 (SQL)
此條目包含過多僅特定讀者會感興趣的過度細節內容。 (2017年5月) |
SELECT是SQL資料操縱語言(DML)中用於查詢表格內欄位資料的指令,可搭配條件限制的子句(如where)或排列順序的子句(如order)來取得查詢結果。
SELECT的基本陳述式格式。
SELECT [ALL | DISTINCT] 欄位名 [,欄位名...] FROM 資料表名 [,資料表名...] [WHERE 篩選條件式] [GROUP BY 欄位名[,欄位名...]] [ORDER BY 欄位名[,欄位名...]]
簡單範例
假設下方範例表格名稱為「T」;表格中有存有二列資料並以C1、C2 兩欄區分資料內容。
C1 | C2 |
---|---|
wiki | 10 |
wikipedia | 100 |
欄位查詢
以「*」代表回傳全部的欄位內容
查詢陳述式 | 回傳結果 | ||||
---|---|---|---|---|---|
SELECT * FROM T;
|
|
或指定只查詢C1欄位資料
查詢陳述式 | 回傳結果 | ||
---|---|---|---|
SELECT C1 FROM T;
|
|
條件限制
以「where」來限制回傳C1欄位中完全符合條件的資料
查詢陳述式 | 回傳結果 | ||
---|---|---|---|
SELECT * FROM T WHERE C1 = 'wiki';
|
|
以「where」搭配「like」來回傳C1欄位中相似符合條件的資料
查詢陳述式 | 回傳結果 | ||||
---|---|---|---|---|---|
SELECT * FROM T WHERE C1 like 'wiki%';
|
|
利用運算比較式來回傳C2欄位中符合數值大小的資料
查詢陳述式 | 回傳結果 | ||
---|---|---|---|
SELECT * FROM T WHERE C2 > 50;
|
|
語意
SELECT陳述式內部各組成部分的理論計算順序,依次為:[1]
- FROM的表連接;
- 笛卡爾積
- ON連接條件篩選(完成了內部連接)
- 添加外部連接的行
- WHERE子句篩選出滿足條件的行集;
- GROUP BY子句對行集中的行做分組合併,使得多個行對應於結果集中的一行;
- 應用HAVING子句從中間結果篩選出滿足條件的行的集合;
- SELECT的結果列中的表達式,然後是DISTINCT關鍵字處理(如果有的話)。因此,在SELECT中給結果集中的列指定別名,是無法被WHERE子句或者GROUP BY子句或者HAVING可見並使用的。
- 應用ORDER BY子句對結果集中的行排序。
- 如果存在TOP或OFFSET/FETCH,對結果行的挑選。
如果使用了GROUP BY子句做分組合併,之後要參照的列必須是或者出現在GROUP BY子句中,或者被包含在聚合函數(如SUM、COUNT等)中。否則編譯會報錯。這是因為,上述兩種情形的列對於每一個分組都有確定的單一值;而上述兩種情形以外的列,對於每一個分組,有可能對應於原始行集的多個行從而具有多個不同的值,那麼選擇哪個值作為該分組的該列的值?無從選擇。聚合函數計算時忽略掉列值為NULL的行。
HAVING子句是在分組後再做篩選,所以HAVING子句中可以包含聚合函數;而WHERE子句就不能包含聚合函數,因為WHERE子句是在分組之前計算的,那時根本無從計算聚合函數。例如,對銷售表依據客戶名稱做分組合併,然後篩選出每個客戶的訂單合計金額大於100萬元的情形,從而得到規模以上大客戶的清單。
使用ORDER BY子句,可以按照單個列排序,也可以依次按照多個列排序,也可以按照結果集中列的別名排序,還可以使用結果集之外的列排序。但是,如果已經指定了SELECT DISTINCT或者該陳述式包含了GROUP BY子句,或是包含了UNION運算子,則排序列必須包含在結果集的列中。這是因為,在上述情形,原數據或者中間表的多個行對應於結果集中的一行;排序列如果不出現在結果集的列中,那麼就可能使結果集中的一行對應於多行從而有了多個排序列的值,這行的排序情況就不唯一導致無從確定其排序後的順位。可以使用ASC或者DESC關鍵字制定升序或降序,預設為升序。
對於排序來說,更複雜的是不同字元編碼所帶來的比較規則的不同。例如,ASCII字串的字典序比較與Unicode字串的字典序比較,就完全不同。可以使用COLLATE子句指定顯式排序規則。比較運算子以及MAX、MIN、BETWEEN、LIKE、IN等運算子都涉及到排序規則。
篩選條件表達式,可以使用=(相等)、>、<、>=、<=、<>等比較運算子,NOT邏輯非、AND、OR等邏輯運算子,BETWEEN或者NOT BETWEEN表示開區間或者其補集的所有值,IN關鍵字列出所有可行值(特別是在子查詢中),LIKE關鍵字用於模式匹配查詢。模式包括%代表任意字串,_代表單個任意字元,[]表示指定範圍內的單個字元,[^]表示不在指定範圍內的單個字元。可以用ESCAPE關鍵字定義跳脫字元,或者用[]包含按照字面使用的字元。
NULL值計算使用三值邏輯。謂詞計算結果為TRUE、FALSE或者UNKNOWN。對於篩選條件表達式,SQL只接受TRUE。對於CHECK約束則是拒絕FALSE。兩個NULL值是否相等,這取決於是否遵從ANSI標準。可以使用謂詞IS NULL或者IS NOT NULL使得結果確定且唯一。 在GROUP BY或者ORDER BY子句,分組或排序時兩個NULL視為相等。
對結果集中的列,可以使用關鍵字TOP選項,限制結果集中返回行數或者行數所佔百分比。還可以緊隨其後使用關鍵字WITH TIES,返回原結果集中最後一行的排序欄位相等的所有行。例如,返回原始數據表中某列最大的那一行,如果使用關鍵字WITH TIES就會把並列最大的多行全部返回。
在SELECT之後緊隨關鍵字DISTINCT,使得結果集中不含重複的行。關鍵字DISTINCT也可用於函數參數。
子查詢是巢狀於SELECT、INSERT、UPDATE、DELETE等陳述式中的查詢。按照子查詢返回結果的數量,分為純量子查詢和多值子查詢;按照對外部查詢的依賴性,分為獨立子查詢和相關子查詢。子查詢出現在SELECT陳述式的結果列表中,那麼子查詢應該是返回單一值;這種子查詢往往可以用表的Join操作代替。子查詢用在WHERE子句的表達式中,可以返回單一值用於比較運算子(>、<、>=等等)之後;也可以返回多值且有ANY、SOME、ALL等關鍵字字首用於比較運算子之後;還可以返回多值與關鍵字IN、EXISTS、NOT IN、NOT EXISTS連用。子查詢可以巢狀子查詢。
資料參考
- ^ Itzik Ben-Gan:《Microsoft Sql Server 2012 high-performance T-sql using windows functions》
- 深入淺出SQL (HeadFirst SQL). 歐萊禮 (O'REILLY). 2008. ISBN 978-986-6840-16-6.
- MySQL 5 徹底研究 第三版 (The Definitive Guide to MySQL5 3ed). 博碩文化. 2006. ISBN 957-527-908-5.