1. 程式人生 > >Oracle DB 使用子查詢來解決查詢

Oracle DB 使用子查詢來解決查詢

目的 滿足 多少 group 錯誤 water 列表 功能 產生

? 定義子查詢 ? 描述子查詢可以解決的問題類型 ? 列出子查詢的類型 ? 編寫單行和多行子查詢 ? 子查詢:類型、語法和準則 ? 單行子查詢: – 子查詢中的組函數 – 帶有子查詢的HAVING子句 ? 多行子查詢 – 使用ALL或ANY運算符 ? 使用EXISTS運算符 ? 子查詢中的空值
  • 使用子查詢解決問題
誰的薪金高於Abel 的薪金? 子查詢: Abel 的薪金是多少? 主查詢: 哪些雇員的薪金高於Abel 的薪金? 使用子查詢解決問題 假設要編寫一個查詢來找出誰的薪金高於Abel 的薪金。 要解決此問題,需要使用兩個查詢:一個查詢用於查找Abel 的薪金,另一個查詢用於查找薪金超過該金額的人員。 通過組合這兩個查詢,即將一個查詢放在另一個查詢中,可以解決此問題。 內部查詢(即子查詢)會返回一個外部查詢(即主查詢)要使用的值。使用子查詢等同於執行兩個連續的查詢,而且將第一個查詢的結果用作第二個查詢中的搜索值。
  • 子查詢語法
? 先執行子查詢(內部查詢),再執行主查詢(外部查詢)。 ? 主查詢會使用子查詢的結果。
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語句中僅返回一行的查詢 ? 多行子查詢:從內部SELECT語句中返回多行的查詢 註:此外,還有多列子查詢,此類查詢從內部SELECT語句中返回多個列。
  • 單行子查詢
僅返回一行 使用單行比較運算符 技術分享 單行子查詢是從內部SELECT語句中返回一行的一種查詢。此類子查詢使用單行運算符。 上圖給出了單行運算符的列表。 示例: 顯示其職務ID 與雇員141 的職務ID 相同的雇員:
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子句
? Oracle Server 會先執行子查詢。 ? Oracle Server 會將結果返回到主查詢的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。
  • 內部查詢沒有返回任何行
因為沒有名為“Haas”的雇員,所以子查詢沒有返回任何行。
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 employee_id, last_name, job_id, salary FROM employees WHERE salary < ALL (SELECT salary FROM employees WHERE job_id = ‘IT_PROG‘) AND job_id <> ‘IT_PROG‘; 在多行子查詢中使用ALL運算符 ALL運算符用於將某個值與子查詢返回的每個值進行比較。示例顯示薪金低於職務ID 為IT_PROG的任何雇員的薪金且職務不是IT_PROG的雇員。 >ALL表示大於最高值, 而<ALL表示小於最低值。 NOT運算符可以與IN、ANY和ALL運算符一起使用。 參考:http://blog.csdn.net/rlhua/article/details/12006433 使用EXISTS運算符
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);

  • 小結
子查詢是一個SELECT語句,它嵌入到另一個SQL 語句的子句中。當查詢基於帶有未知中間值的搜索標準時,使用子查詢非常有幫助。 子查詢具有以下特性: ? 可以將一行數據傳遞給包含單行運算符(如=、<>、>、>=、<或<=)的主語句 ? 可以將多行數據傳遞給包含多行運算符(如IN)的主語句 ? Oracle Server 先處理子查詢,隨後WHERE或HAVING子句會使用生成的結果 ? 可以包含組函數

Oracle DB 使用子查詢來解決查詢