Oracle 子查询

1、子查询语法

  1. SELECT select_list
  2. FROM table1
  3. WHERE expr operator
  4. (SELECT select_list
  5. FROM table1);
  1. SELECT last_name
  2. FROM employees
  3. WHERE salary >
  4. (SELECT salary
  5. FROM employees
  6. WHERE last_name = 'Abel');

image.png

2、子查询注意点

单行比较必须对应单行子查询(返回单一结果值的查询); 比如= , >
多行比较必须对应多行子查询(返回一个数据集合的查询);比如 IN , > ANY, > ALL 等

A.单行子查询

  1. SELECT employee_id, last_name
  2. FROM employees
  3. WHERE salary =
  4. (SELECT MIN(salary)
  5. FROM employees);

image.png

B.多行子查询

  1. SELECT employee_id, last_name, job_id, salary
  2. FROM employees
  3. WHERE salary < ANY
  4. (SELECT salary
  5. FROM employees
  6. WHERE job_id = 'IT_PROG')
  7. AND job_id <> 'IT_PROG';

3、子查询进阶

A.非相关子查询当作一张表来用

  1. SELECT a.last_name, a.salary,
  2. a.department_id, b.salavg
  3. FROM employees a, (SELECT department_id,
  4. AVG(salary) salavg
  5. FROM employees
  6. GROUP BY department_id) b
  7. WHERE a.department_id = b.department_id
  8. AND a.salary > b.salavg;

image.png

B.子查询中参考了外部主查询中的表

  1. SELECT last_name, salary, department_id
  2. FROM employees outer
  3. WHERE salary > (SELECT AVG(salary)
  4. FROM employees
  5. WHERE department_id =
  6. outer.department_id) ;
  1. SELECT e.employee_id, last_name,e.job_id
  2. FROM employees e
  3. WHERE 2 <= (SELECT COUNT(*)
  4. FROM job_history
  5. WHERE employee_id = e.employee_id);

C.使用Exists操作

  1. SELECT employee_id, last_name, job_id, department_id
  2. FROM employees outer
  3. WHERE EXISTS ( SELECT 'X'
  4. FROM employees
  5. WHERE manager_id =
  6. outer.employee_id);
  7. SELECT employee_id,last_name,job_id,department_id
  8. FROM employees
  9. WHERE employee_id IN (SELECT manager_id
  10. FROM employees
  11. WHERE manager_id IS NOT NULL);

D.使用Not Exists操作

  1. SELECT department_id, department_name
  2. FROM departments d
  3. WHERE NOT EXISTS (SELECT 'X'
  4. FROM employees
  5. WHERE department_id
  6. = d.department_id);
  7. SELECT department_id, department_name
  8. FROM departments
  9. WHERE department_id NOT IN (SELECT department_id
  10. FROM employees);

注意:Not In 里面只要有一个NULL ,就不成立了,这是很容易出错的地方; 正确的方法请在后 面的子查询中加上where department_id is not null;

E.在Update 语句中使用相关子查询

  1. ALTER TABLE employees
  2. ADD(department_name VARCHAR2(14));
  3. UPDATE employees e
  4. SET department_name =
  5. (SELECT department_name
  6. FROM departments d
  7. WHERE e.department_id = d.department_id);

F.在DELETE 语句中使用相关子查询

  1. DELETE FROM job_history JH
  2. WHERE employee_id =
  3. (SELECT employee_id
  4. FROM employees E
  5. WHERE JH.employee_id = E.employee_id
  6. AND start_date =
  7. (SELECT MIN(start_date)
  8. FROM job_history JH
  9. WHERE JH.employee_id = E.employee_id)
  10. AND 5 > (SELECT COUNT(*)
  11. FROM job_history JH
  12. WHERE JH.employee_id = E.employee_id
  13. GROUP BY employee_id
  14. HAVING COUNT(*) >= 4));

I.使用WITH子句

  1. WITH
  2. dept_costs AS (
  3. SELECT d.department_name, SUM(e.salary) AS dept_total
  4. FROM employees e, departments d
  5. WHERE e.department_id = d.department_id
  6. GROUP BY d.department_name),
  7. avg_cost AS (
  8. SELECT SUM(dept_total)/COUNT(*) AS dept_avg
  9. FROM dept_costs)
  10. SELECT *
  11. FROM dept_costs
  12. WHERE dept_total >
  13. (SELECT dept_avg
  14. FROM avg_cost)
  15. ORDER BY department_name;

使用WITH好处:
1)如果在后面多次使用则可以简化SQL ;
2)适当提高性能;