查詢 (SQL)

结构化查询语言语句

SELECTSQL資料操縱語言(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;
wiki 10
wikipedia 100

或指定只查詢C1欄位資料

查詢語句 回傳結果
SELECT C1 FROM T;
wiki
wikipedia

條件限制

以「where」來限制回傳C1欄位中完全符合條件的資料

查詢語句 回傳結果
SELECT * FROM T WHERE C1 = 'wiki';
wiki 10

以「where」搭配「like」來回傳C1欄位中相似符合條件的資料

查詢語句 回傳結果
SELECT * FROM T WHERE C1 like 'wiki%';
wiki 10
wikipedia 100

利用運算比較式來回傳C2欄位中符合數值大小的資料

查詢語句 回傳結果
SELECT * FROM T WHERE C2 > 50;
wikipedia 100

語義

SELECT語句內部各組成部分的理論計算順序,依次為:[1]

  1. FROM的表連接;
    1. 笛卡爾積
    2. ON連接條件篩選(完成了內部連接)
    3. 添加外部連接的行
  2. WHERE子句篩選出滿足條件的行集;
  3. GROUP BY子句對行集中的行做分組合併,使得多個行對應於結果集中的一行;
  4. 應用HAVING子句從中間結果篩選出滿足條件的行的集合;
  5. SELECT的結果列中的表達式,然後是DISTINCT關鍵字處理(如果有的話)。因此,在SELECT中給結果集中的列指定別名,是無法被WHERE子句或者GROUP BY子句或者HAVING可見並使用的。
  6. 應用ORDER BY子句對結果集中的行排序。
  7. 如果存在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連用。子查詢可以嵌套子查詢。

資料參考

  1. ^ Itzik Ben-Gan:《Microsoft Sql Server 2012 high-performance T-sql using windows functions》

外部連結