子查詢
查詢(query) 任何SQL語句都是查詢。但此術語一般指SELECT語句。
SQL還允許創建子查詢(subquery),即嵌套在其他查詢中的查詢。
利用子查詢進行過濾
例子:假如需要列出訂購物品RGAN01的所有客戶
(1) 檢索包含物品RGAN01的所有訂單的編號。
(2) 檢索具有前一步驟列出的訂單編號的所有客戶的ID。
(3) 檢索前一步驟返回的所有客戶ID的客戶信息。
輸入
SELECT order_num
FROM OrderItems
WHERE prod_id = 'RGAN01';
輸出
+-----------+
| order_num |
+-----------+
| 20007 |
| 20008 |
+-----------+
輸入
SELECT cust_id
FROM Orders
WHERE order_num IN (20007,20008);
輸出
+------------+
| cust_id |
+------------+
| 1000000004 |
| 1000000005 |
+------------+
輸入
SELECT cust_id
FROM orders
WHERE order_num IN (SELECT order_num
FROM orderitems
WHERE prod_id = 'RGAN01');
輸出
+------------+
| cust_id |
+------------+
| 1000000004 |
| 1000000005 |
+------------+
分析:在SELECT語句中,子查詢總是從內向外處理。在處理上面的SELECT語句時,MySQL實際上執行了兩個操作
首先是:
SELECT order_num FROM orderitems WHERE prod_id = ‘RGAN01’
次查詢返回連個訂單號:20007和20008。然後這兩個值以IN操作符要求的逗號分隔的格式傳遞給外部查詢的WHERE子句。
外部查詢完成:
SELECT cust_id FROM orders WHERE order_num IN(20007,20008)
可以看到,輸出是正確的並與前面硬編碼WHERE子句所返回的值相同。
現在得到了訂購物品RGAN01的所有客戶的ID。下一步是檢索這些客戶ID的客戶信息。
輸入
SELECT cust_name,cust_contact
FROM customers
WHERE cust_id IN ('1000000004','1000000005');
可以把其中的WHERE子句轉換爲子查詢而不是硬編碼這些客戶ID:
輸入
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 = 'RGAN01'));
輸出
+---------------+--------------------+
| cust_name | cust_contact |
+---------------+--------------------+
| Fun4All | Denise L. Stephens |
| The Toy Store | Kim Howard |
+---------------+--------------------+
分析:
爲了執行上述SELECT語句,MySQL實際上必須執行3條SELECT語句。最裏邊的子查詢返回訂單號列表,此列表用於其外面的子查詢的WHERE子句。外面的子查詢返回客戶ID列表,此客戶ID列表用於最外層查詢的WHERE子句。最外層查詢確實返回所需的數據。
作爲計算字段使用子查詢
使用子查詢的另一方法是創建計算字段。假如需要顯示customers表中每個客戶的訂單總數。訂單與相應的客戶ID存儲在orders表中。
爲了執行這個操作,遵循下面的步驟。
(1) 從customers表中檢索客戶列表。
(2) 對於檢索出的每個客戶,統計其在orders表中的訂單數目。
使用SELECT COUNT(*)對錶中的行進行計數,並且通過提供一條WHERE子句來過濾某個特定的客戶ID,可僅對該客戶的訂單進行計數。
爲了對每個客戶執行COUNT(*)計算,應該將COUNT(*)作爲一個子查詢。
輸入
SELECT cust_name,
cust_state,
(SELECT COUNT(*)
FROM orders
WHERE orders.cust_id = customers.cust_id) AS orders
FROM customers
ORDER BY cust_name;
輸出
+---------------+------------+--------+
| cust_name | cust_state | orders |
+---------------+------------+--------+
| Fun4All | IN | 1 |
| Fun4All | AZ | 1 |
| Kids Place | OH | 0 |
| The Toy Store | IL | 1 |
| Village Toys | MI | 2 |
+---------------+------------+--------+
分析:這條SELECT語句對customers表中每個客戶返回3列:cust_name、cust_state和orders。orders是一個計算字段,它是由圓括號中的子查詢建立的。該子查詢對檢索出的每個客戶執行一次。在此例子中,該子查詢執行了5次,因爲檢索出了5個客戶。
子查詢中的WHERE子句與前面使用的WHERE子句稍有不同,因爲它使
用了完全限定列名(在第4章中首次提到)。下面的語句告訴SQL比較
orders表中的cust_id與當前正從customers表中檢索的cust_id:
WHERE orders.cust_id = customers.cust_id
相關子查詢(correlated subquery) 涉及外部查詢的子查詢。
這種類型的子查詢稱爲相關子查詢。
任何時候只要列名可能有多義性,就必須使用這種語法(表名和列名由一個句點分隔)。