子查詢:
用子查詢能解決的問題
假想你想要寫一個查詢來找出掙錢比陸濤的薪水還多的人。為了解決這個問題,你需要兩個查詢:一
個找出陸濤的收入,第二個查詢找出收入高于陸濤的人。
你可以用組合兩個查詢的方法解決這個問題,放置一個查詢到另一個查詢中。
內查詢或子查詢返回一個值給外查詢或主查詢。使用一個子查詢相當于執行兩個連續查詢并且用第一個
查詢的結果作為第二個查詢的搜索值。
子查詢語法:
SELECT select_list
FROM table
WHERE expr operator
(SELECT select_list
FROM table);
1.子查詢(內查詢) 在主查詢之前執行一次
2.子查詢的結果被用于主查詢(外查詢)
首先執行子查詢 (內查詢) 顯示子查詢返回的值,然后用內查詢返回的結果執行外查詢,最后,執行整個查詢 (包括子查詢),顯示相同的結果。
子查詢可嵌套的位置:
子查詢是一個SELECT 語句,它是嵌在
另一個 SELECT 語句中的子句。
使用子查詢你可以用簡單的語句構建功能強大的語句。當你需要從表中用依賴于表本身的數據選擇行時
它們是非常有用的。
也可以放在
WHERE 子句 HAVING 子句 FROM 子句。
在語法中:
operator 包括比較條件,例如 >、= 或 IN
比較條件分為兩個種類:單行運算符 (>, =, >=, <, <>, <=) 和多行運算符 (IN, ANY, ALL)。
子查詢通常涉及一個嵌套的 SELECT、子-SELECT 或內 SELECT 語句。字查詢通常執行一次。并且它的輸出被用于完成主或外查詢的查詢條件。
另外,子查詢可以被放在 CREATE VIEW 語句中、CREATE TABLE 語句、UPDATE 語句、INSERT 語句的 INTO 子句和 UPDATE 語句的 SET 子句中。
使用子查詢的原則:
1. 子查詢放在圓括號中
2.將子查詢放在比較條件的右邊, 可以增加可讀性。
在子查詢中的ORDER BY 子句不需要,除非你正在執行Top-N 分析。
Oracle8i 以前的版本中,子查詢不包含 ORDER BY 子句。對一個 SELECT 語句只能用一個 ORDER BY 子句,并且如果指定了它就必須放在主 SELECT 語句的最后。從 Oracle8i 開始,ORDER BY 子句可以使用,并且在進行 Top-N 分析時是必須的。
3.在單行子查詢中用單行運算符,在多行子查詢中用多行運算符,
在子查詢中可以使用兩種比較條件:單行運算符和多行運算符。
子查詢的個數:
Oracle 服務器沒有強制限制子查詢的數目;限制只與查詢所需的緩沖區大小有關。
子查詢的類型:
1. 單行子查詢:從內 SELECT 語句只返回一行的查詢
2. 多行子查詢:從內 SELECT 語句返回多行的查詢
3. 還有多列子查詢:從內 SELECT 語句返回多列的查詢。
單行子查詢
單行子查詢是從內查詢返回一行的查詢。在該子查詢類型中用一個單行操作符
SELECT last_name, job_id
FROM employees
WHERE job_id =
(SELECT job_id
FROM employees
WHERE employee_id = 141);
SELECT last_name, job_id, salary
FROM employees
WHERE job_id =
(SELECT job_id FROM employees WHERE employee_id = 141) AND salary >(SELECT salary FROM employees WHERE employee_id = 143);
該例子可以由三個查詢塊組成:外查詢和兩個內查詢。內查詢塊首先被執行,產生查詢結果分別為 ST_CLERK 和 2600。然后處理外查詢塊,并且使用內查詢的返回值來完成它的查詢條件。
兩個內查詢返回單個值 (分別是 ST_CLERK 和 2600),所以這種 SQL 語句被稱為單行子查詢。
注:外和內查詢可以從不同的表中取得數據。
在子查詢中使用組函數:
SELECT last_name, job_id, salary
FROM employees
WHERE salary =
(SELECT MIN(salary) FROM employees);
你可以從主查詢中顯示數據,該主查詢使用一個帶組函數的單行子查詢。子查詢放在圓括號中并且放在比較條件的后面。
例子顯示所有其薪水等于最低薪水的雇員的 last name、job ID 和 salary。 MIN 組函數返回單個的值 (2500) 給外函數。
帶子查詢的HAVING 子句:
1.Oracle 服務器首先執行子查詢
2.Oracle 服務器返回結果到主查詢的HAVING 子句中
例
找出平均薪水為最低平均薪水的工作崗位。
SELECT job_id, AVG(salary)
FROM employees
GROUP BY job_id
HAVING AVG(salary) = (SELECT MIN(AVG(salary))
FROM employees
GROUP BY job_id);
子查詢錯誤
使用子查詢的一個常見的錯誤是單行子查詢返回返回了多行。
SELECT employee_id, last_name
FROM employees
WHERE salary =
(SELECT MIN(salary) FROM employees GROUP BY department_id);
ERROR at line 4:ORA-01427: single-rowsubqueryreturns more thanone rowERROR
子查詢包含一個 GROUP BY 子句,這就暗示該子查詢將返回多行,每個對應它所找到的一組,在這種情況下,子查詢的結果將是 4400、6000、2500、4200、7000、17000 和 8300。
外查詢得到子查詢的結果 (4400、6000、2500、4200、7000、17000、8300) 并且在它的 WHERE 子句中使用這些結果。WHERE 子句包含一個等號 (=) 運算符,這是一個單行比較運算符,只能使用一個值。 = 操作符不能接受來自子查詢的多個值,并且因此產生錯誤。
為了糾正該錯誤,改變 = 操作為 IN。
子查詢的另一個常見問題是內查詢沒有返回行。
,子查詢包含一個 WHERE 子句,推測起來,其目的是找名字為 Haas 的雇員,該語句是正確的,但在執行時選擇無行返回。
沒有名叫 Haas 的雇員,所以子查詢無返回行,外查詢得到子查詢的結果 (null) 并且在 WHERE 子句中使用該結果,外查詢找不到一個 job ID 等于 null 的雇員,所以也沒有行返回。如果一個 job 存在 null 值,也沒有返回行,因為比較兩個空值還是空,因此 WHERE 子句的條件不為 true。
多行子查詢:
多行子查詢
子查詢返回多行被稱為多行子查詢。對多行子查詢要使用多行運算符而不是單行運算符。多行運算符期待多個值。
例
查找各部門收入為部門最低的那些雇員。
SELECT last_name, salary, department_id
FROM employees
WHERE salary IN (SELECT MIN(salary)
FROM employees
GROUP BY department_id);
內查詢先被執行,產生一個查詢結果,然后主查詢塊處理和使用由內查詢返回的值完成它的搜索條件。事實上,在 Oracle 服務器看起來主查詢象是下面這樣:
SELECT last_name, salary, department_id
FROM employees
WHERE salary IN (2500, 4200, 4400, 6000, 7000, 8300, 8600, 17000);
在多行子查詢中使用ANY 運算符
SELECT employee_id, last_name, job_id, salary
FROM employees
WHERE salary < ANY(SELECT salaryFROM employeesWHERE job_id = 'IT_PROG')
AND job_id <> 'IT_PROG';
ANY 運算符 (和它的同義詞, SOME 運算符) 比較一個值與一個子查詢返回的每一個值。幻燈片中的例子顯示不是 IT 程序員的雇員,并且這些雇員的的薪水少于IT 程序員。掙錢最多的程序員的薪水是 $9,000。
<ANY