• 定义子查询
• 描述子查询可以解决的问题类型
• 列出子查询的类型
• 编写单行和多行子查询
 
• 子查询:类型、语法和准则
• 单行子查询:
– 子查询中的组函数
– 带有子查询的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。
 
 
  • 在多行子查询中使用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运算符一起使用。
 
 
使用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 使用子查询来解决查询的更多相关文章

  1. Oracle02——oracle分页、子查询、集合运算、处理数据、创建和管理表和其他数据库对象

    作者: kent鹏 转载请注明出处: http://www.cnblogs.com/xieyupeng/p/7289451.html --oracle分页(Pageing Query) select ...

  2. .Net程序员学用Oracle系列(14):子查询、集合查询

    1.子查询 1.1.子查询简介 1.2.WITH 子查询 2.集合查询 2.1.UNION 和 UNION ALL 2.2.MINUS 2.3.INTERSECT 2.4.集合运算与 ORDER BY ...

  3. Oracle with重用子查询

    --with 重用子查询对于多次使用相同子查询的复杂查询语句来说,用户可能会将查询语句分成两条语句执行.第一条语句将子查询结果存放到临时表,第二条查询语句使用临时表处理数据.从 Oracle 9i 开 ...

  4. Oracle子查询(嵌套查询)

    概念: 所谓子查询,即一个select语句中嵌套了另外的一个或者多个select语句 需求:查找和Smith同部门的所有员工的id和last_name 目标: 员工id,last_name from: ...

  5. oracle数据库之子查询

    子查询也叫内部查询,在主查询之前执行一次并得到结果,此结果一般情况下,是用来当做是主查询的条件.   -- 在 emp 表中,找出工资比 ALLEN 的高? -- 先查出 ALLEN 的工资是多少? ...

  6. Oracle系列七 子查询

    子查询语法 SELECT select_list FROM table WHERE expr operator (SELECT select_list FROM table); 子查询 (内查询) 在 ...

  7. Oracle笔记(六) 多表查询

    最近看了李兴华的oracle视频,这是网上别人做的笔记非常细致,分享给大家,第六篇 原创地址:http://www.cnblogs.com/mchina/archive/2012/09/07/2651 ...

  8. SQL-在Update中进行子查询和左联查询

    以下总结源自后边的三个参考思索和测试而来: 我们有一张行政区划表,为了查询速度的优化,我们需要在这张表中,将每个乡镇的记录中写入其所属的省.市.县, 表如下: 当然,我们可以使用游标或在存储过程中使用 ...

  9. 30多条mysql数据库优化方法,千万级数据库记录查询轻松解决(转载)

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...

随机推荐

  1. Redis 应用:缓存

    使用Redis做预定库存缓存功能 缓存是在业务层做的,准确讲应该是在MVC模型中Model的ORM里面 PHP项目的缓存从以前的APC缓存逐渐切换到Redis中,并且根据Redis所支持的数据结构做了 ...

  2. shell script 脚本编程

    介绍 Shell脚本编程30分钟入门 Shell 教程 Linux 的 Shell 种类众多,常见的有: Bourne Shell(/usr/bin/sh或/bin/sh) Bourne Again ...

  3. 3、lvs调度方法详解

    3.lvs类型和调度方法详解    http://www.178linux.com/13570 集群:将多台主机组织起来满足某一特定需求: 集群类型: LB:Load Balancing, 负载均衡集 ...

  4. HttpPost

    public static string HttpPost(string url, string postData, bool isPost = true) { string method = isP ...

  5. C#中引用第三方ocx控件引发的问题以及解决办法

    调用OCX控件的步骤:1.在系统中注册该ocx控件,命令:regsvr32.exe 控件位置(加 /u 参数是取消注册)2.在.net的工具箱中添加该控件,拖到form中去就可以了. 不用工具箱的话, ...

  6. 中文字符串和UTF-8编码字符串相互转换

    中文字符串和UTF-8编码字符串相互转换 //UTF字符转换 var UTFTranslate = { Change: function(pValue) { ) { ).replace(/(%u)(\ ...

  7. Android drag drop

    最近偶尔知道了锤子的one step,所以在网上看相关的东西,有人说android原生drag drop就能实现,我就去学习一下这个drag drop,下面把学习到的东西总结一下: drag drop ...

  8. leecode第六十二题(不同路径)

    class Solution { public: int uniquePaths(int m, int n) { ||n==) ; vector<vector<int>> pa ...

  9. ES6 学习笔记(整理一遍阮一峰大神得入门文档,纯自己理解使用)

    1.let命令 1)let和var的区别:let声明的变量只有所在的代码块有效. 2)没有变量的提升,一定要声明后使用.使用let命令声明变量之前,该变量都是不可用的.形成“暂时性死区”. 3)typ ...

  10. SQL中的where条件,在数据库中提取与应用浅析

    1. 问题描述 一条SQL,在数据库中是如何执行的呢?相信很多人都会对这个问题比较感兴趣.当然,要完整描述一条SQL在数据库中的生命周期,这是一个非常巨大的问题,涵盖了SQL的词法解析.语法解析.权限 ...