Oracle DB 使用子查詢來解決查詢
阿新 • • 發佈:2017-07-03
目的 滿足 多少 group 錯誤 water 列表 功能 產生 ? 定義子查詢
? 描述子查詢可以解決的問題類型
? 列出子查詢的類型
? 編寫單行和多行子查詢
? 子查詢:類型、語法和準則
? 單行子查詢:
– 子查詢中的組函數
– 帶有子查詢的HAVING子句
? 多行子查詢
– 使用ALL或ANY運算符
? 使用EXISTS運算符
? 子查詢中的空值
- 使用子查詢解決問題
- 子查詢語法
SELECT select_list FROM table WHERE expr operator (SELECT select_list FROM table);
子查詢是一個SELECT語句,它嵌入到另一個SELECT語句的子句中。通過使用子查詢,可以用簡單的語句構建功能強大的語句。當需要從表中選擇行,而選擇條件卻取決於該表自身中的數據時,子查詢非常有用。 可以在許多SQL 子句中使用子查詢,其中包括以下子句: ? WHERE子句 ? HAVING子句 ? FROM子句 在該語法中: operator包括比較條件,例如>、=或IN 註:比較條件分為以下兩類:單行運算符(>、=、>=、<、<>、<=)和多行運算符(IN、ANY、ALL、EXISTS)。 子查詢通常被稱為嵌套SELECT語句、子SELECT語句或內部SELECT語句。通常先執行子查詢,然後使用其輸出來完善主查詢(即外部查詢)的查詢條件。
- 使用子查詢
SELECT last_name, salary FROM employees WHERE salary > (SELECT salary FROM employees WHERE last_name = ‘Abel‘);
在示例中,內部查詢確定了雇員Abel 的薪金。外部查詢會采用內部查詢的結果並根據此結果顯示薪金超過雇員Abel 的所有雇員。
- 使用子查詢的準則
- 子查詢的類型
- 單行子查詢
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 last_name= ‘Taylor‘) AND salary > (SELECT salary FROM employees WHERE last_name= ‘Taylor‘);
可以將SELECT語句看作一個查詢塊。示例顯示其職務與Taylor 相同但薪金高於Taylor 的雇員。 該示例由三個查詢塊組成:一個外部查詢和兩個內部查詢。先執行內部查詢塊,生成的查詢結果分別為SA_REP和8600。然後可以處理外部查詢塊,使用內部查詢返回的值來完善其搜索條件。 兩個內部查詢都返回單個值(分別為SA_REP和8600),因此將此SQL 語句稱為單行子查詢。 註:外部查詢和內部查詢可以從不同的表中獲得數據。
- 在子查詢中使用組函數
SELECT last_name,job_id, salary FROM employees WHERE salary = (SELECT MIN(salary) FROM employees);
通過在子查詢中使用組函數來返回單行,可以從主查詢中顯示數據。子查詢包含在括號中,位於比較條件之後。 示例顯示其薪金等於最低薪金的所有雇員的姓氏、職務ID 和薪金。MIN組函數將單個值(2500) 返回給外部查詢。
- 帶有子查詢的HAVING子句
SELECT department_id, MIN(salary) FROM employees GROUP BY department_id HAVING MIN(salary) > (SELECT MIN(salary) FROM employees WHERE department_id = 50);
不僅可以在WHERE子句中使用子查詢,還可以在HAVING子句中使用子查詢。Oracle 服務器會執行子查詢,並將結果返回到主查詢的HAVING子句中。 示例中的SQL 語句顯示最低薪金高於部門50 的最低薪金的所有部門。 示例: 查找具有最低平均薪金的職務。
SELECT job_id, AVG(salary) FROM employees GROUP BY job_id HAVING AVG(salary) = (SELECT MIN(AVG(salary)) FROM employees GROUP BY job_id);
- 此語句中有什麽錯誤
Connected. hr@TEST0924> SELECT employee_id, last_name FROM employees 2 WHERE salary = 3 (SELECT MIN(salary) FROM employees GROUP BY department_id); (SELECT MIN(salary) FROM employees GROUP BY department_id) * ERROR at line 3: ORA-01427: single-row subquery returns more than one row
子查詢的常見錯誤是單行子查詢返回了多行。 在示例的SQL 語句中,子查詢包含一個GROUP BY子句,這意味著該子查詢將返回多行,每行都對應於一個它找到的組。這種情況下,子查詢的結果為4400、6000、 2500、4200、7000、17000和8300。 外部查詢將采用這些結果,並在其WHERE子句中使用它們。該WHERE子句包含一個等於(=) 運算符,該運算符是一個只需要一個值的單行比較運算符。=運算符無法接受子查詢中的多個值,因此產生了錯誤。 要更正此錯誤,請將=運算符更改為IN。
- 內部查詢沒有返回任何行
hr@TEST0924> SELECT last_name, job_id FROM employees 2 WHERE job_id = 3 (SELECT job_id FROM employees WHERE last_name = ‘Haas‘);
no rows selected 子查詢的另外常見問題是內部查詢沒有返回任何行。 在示例的SQL 語句中,子查詢包含一個WHERE子句。據推測,該語句的目的是要查找名為Haas 的雇員。該語句正確,但是因為沒有名為“Haas”的雇員,所以執行時沒有選擇任何行。因此,子查詢不會返回任何行。 外部查詢采用子查詢的結果(空值),並在其WHERE子句中使用這些結果。外部查詢沒有找到職務ID 等於空值的雇員,因此不會返回任何行。即使存在值為空的職務,也不會返回行,因為兩個空值的比較會產生一個空值,從而使WHERE條件不為“真”。
- 多行子查詢
SELECT last_name, salary, department_id FROM employees WHERE salary IN (SELECT MIN(salary) FROM employees GROUP BY department_id);
示例: 查找其薪金等於各個部門最低薪金的雇員。 先執行內部查詢,生成一個查詢結果。然後可以處理主查詢塊,使用內部查詢返回的值完善其搜索條件。事實上,主查詢將以下面的形式出現在Oracle Server 上:
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 salary FROM employees WHERE job_id = ‘IT_PROG‘) AND job_id <> ‘IT_PROG‘;
ANY運算符(及其同義詞SOME運算符)用於將某個值與子查詢返回的每個值進行比較。 示例顯示不是IT 程序員且薪金低於任一IT 程序員的雇員。程序員的最高薪金為$9,000。 ? <ANY表示低於最高值。 ? >ANY表示高於最低值。 ? =ANY等同於IN。 參考:http://blog.csdn.net/rlhua/article/details/12007309
- 在多行子查詢中使用ALL運算符
SELECT * FROM departments WHERE NOT EXISTS (SELECT * FROM employees WHERE employees.department_id=departments.department_id);
使用EXISTS運算符 在查詢中使用EXISTS運算符,查詢結果取決於某些行是否在表中存在。如果子查詢至少返回一行,則求值結果為TRUE。 示例顯示沒有雇員的部門。對於DEPARTMENTS表中每一行,檢查條件,看一看在EMPLOYEES表中是否存在具有相同部門ID 的行。如果不存在這樣的行,則相應 行滿足條件,從而選擇該行。如果EMPLOYEES表中存在相應行,則不選擇該行。
- 子查詢中的空值
SELECT emp.last_name FROM employees emp WHERE emp.employee_id NOT IN (SELECT mgr.manager_id FROM employees mgr);
示例中的SQL 語句嘗試顯示沒有任何下屬的所有雇員。邏輯上,此SQL 語句應該返回12 行。但是,該SQL 語句沒有返回任何行。因為內部查詢返回的值中有一個為空值,所以整個查詢不會返回任何行。 原因是所有條件與空值進行比較後都會產生一個空值。因此,只要子查詢的結果集中可能包含空值,就不要使用NOT IN運算符。NOT IN運算符等同於<> ALL。 請註意,如果使用的是IN運算符,則子查詢的結果集中存在空值就不會成為問題。IN運算符等同於=ANY。 例如,要顯示具有下屬的雇員,可以使用下面的SQL 語句:
SELECT emp.last_name FROM employees emp WHERE emp.employee_id IN (SELECT mgr.manager_id FROM employees mgr);
另外,可以在子查詢中包括WHERE子句,用來顯示沒有下屬的所有雇員:
SELECT last_name FROM employees WHERE employee_id NOT IN (SELECT manager_id FROM employees WHERE manager_id IS NOT NULL);
- 小結
Oracle DB 使用子查詢來解決查詢