Oracle DB 使用子查询来解决查询.docx
- 文档编号:10339047
- 上传时间:2023-02-10
- 格式:DOCX
- 页数:10
- 大小:18.12KB
Oracle DB 使用子查询来解决查询.docx
《Oracle DB 使用子查询来解决查询.docx》由会员分享,可在线阅读,更多相关《Oracle DB 使用子查询来解决查询.docx(10页珍藏版)》请在冰豆网上搜索。
OracleDB使用子查询来解决查询
•定义子查询
•描述子查询可以解决的问题类型
•列出子查询的类型
•编写单行和多行子查询
•子查询:
类型、语法和准则
•单行子查询:
–子查询中的组函数
–带有子查询的HAVING子句
•多行子查询
–使用ALL或ANY运算符
•使用EXISTS运算符
•子查询中的空值
∙使用子查询解决问题
谁的薪金高于Abel的薪金?
子查询:
Abel的薪金是多少?
主查询:
哪些雇员的薪金高于Abel的薪金?
使用子查询解决问题
假设要编写一个查询来找出谁的薪金高于Abel的薪金。
要解决此问题,需要使用两个查询:
一个查询用于查找Abel的薪金,另一个查询用于查找薪金超过该金额的人员。
通过组合这两个查询,即将一个查询放在另一个查询中,可以解决此问题。
内部查询(即子查询)会返回一个外部查询(即主查询)要使用的值。
使用子查询等同于执行两个连续的查询,而且将第一个查询的结果用作第二个查询中的搜索值。
∙子查询语法
•先执行子查询(内部查询),再执行主查询(外部查询)。
•主查询会使用子查询的结果。
SELECTselect_list FROMtable WHEREexproperator
(SELECTselect_list FROMtable);
子查询是一个SELECT语句,它嵌入到另一个SELECT语句的子句中。
通过使用子查询,可以用简单的语句构建功能强大的语句。
当需要从表中选择行,而选择条件却取决于该表自身中的数据时,子查询非常有用。
可以在许多SQL子句中使用子查询,其中包括以下子句:
•WHERE子句
•HAVING子句
•FROM子句
在该语法中:
operator包括比较条件,例如>、=或IN
注:
比较条件分为以下两类:
单行运算符(>、=、>=、<、<>、<=)和多行运算符(IN、ANY、ALL、EXISTS)。
子查询通常被称为嵌套SELECT语句、子SELECT语句或内部SELECT语句。
通常先执行子查询,然后使用其输出来完善主查询(即外部查询)的查询条件。
∙使用子查询
SELECTlast_name,salary FROMemployees
WHEREsalary>
(SELECTsalary FROMemployees WHERElast_name='Abel');
在示例中,内部查询确定了雇员Abel的薪金。
外部查询会采用内部查询的结果并根据此结果显示薪金超过雇员Abel的所有雇员。
∙使用子查询的准则
•子查询必须放在括号中。
•子查询放在比较条件的右侧可增加可读性。
但是,子查询可出现在比较运算符的任意一侧。
•在子查询中可以使用两类比较条件:
单行运算符和多行运算符。
对单行子查询使用单行运算符,对多行子查询使用多行运算符。
∙子查询的类型
•单行子查询:
从内部SELECT语句中仅返回一行的查询
•多行子查询:
从内部SELECT语句中返回多行的查询
注:
此外,还有多列子查询,此类查询从内部SELECT语句中返回多个列。
∙单行子查询
仅返回一行
使用单行比较运算符
单行子查询是从内部SELECT语句中返回一行的一种查询。
此类子查询使用单行运算符。
上图给出了单行运算符的列表。
示例:
显示其职务ID与雇员141的职务ID相同的雇员:
SELECTlast_name,job_id FROMemployees
WHEREjob_id=
(SELECTjob_id FROMemployees WHEREemployee_id=141);
∙执行单行子查询
SELECTlast_name,job_id,salary FROMemployees
WHEREjob_id=
(SELECTjob_id FROMemployees WHERElast_name='Taylor')
ANDsalary>
(SELECTsalary FROMemployees WHERElast_name='Taylor');
可以将SELECT语句看作一个查询块。
示例显示其职务与Taylor相同但薪金高于Taylor的雇员。
该示例由三个查询块组成:
一个外部查询和两个内部查询。
先执行内部查询块,生成的查询结果分别为SA_REP和8600。
然后可以处理外部查询块,使用内部查询返回的值来完善其搜索条件。
两个内部查询都返回单个值(分别为SA_REP和8600),因此将此SQL语句称为单行子查询。
注:
外部查询和内部查询可以从不同的表中获得数据。
∙在子查询中使用组函数
SELECTlast_name,job_id,salary FROMemployees
WHEREsalary=
(SELECTMIN(salary) FROMemployees);
通过在子查询中使用组函数来返回单行,可以从主查询中显示数据。
子查询包含在括号中,位于比较条件之后。
示例显示其薪金等于最低薪金的所有雇员的姓氏、职务ID和薪金。
MIN组函数将单个值(2500)返回给外部查询。
∙带有子查询的HAVING子句
•OracleServer会先执行子查询。
•OracleServer会将结果返回到主查询的HAVING子句中。
SELECTdepartment_id,MIN(salary) FROMemployees GROUPBYdepartment_id
HAVINGMIN(salary)>
(SELECTMIN(salary) FROMemployees WHEREdepartment_id=50);
不仅可以在WHERE子句中使用子查询,还可以在HAVING子句中使用子查询。
Oracle 服务器会执行子查询,并将结果返回到主查询的HAVING子句中。
示例中的SQL语句显示最低薪金高于部门50的最低薪金的所有部门。
示例:
查找具有最低平均薪金的职务。
SELECTjob_id,AVG(salary) FROMemployees GROUPBYjob_id
HAVINGAVG(salary)=
(SELECTMIN(AVG(salary)) FROMemployees GROUPBYjob_id);
∙此语句中有什么错误
对多行子查询使用了单行运算符
Connected.
hr@TEST0924>SELECTemployee_id,last_nameFROMemployees
2 WHEREsalary=
3 (SELECTMIN(salary)FROMemployeesGROUPBYdepartment_id);
(SELECTMIN(salary)FROMemployeesGROUPBYdepartment_id)
*
ERRORatline3:
ORA-01427:
single-rowsubqueryreturnsmorethanonerow
子查询的常见错误是单行子查询返回了多行。
在示例的SQL语句中,子查询包含一个GROUPBY子句,这意味着该子查询将返回多行,每行都对应于一个它找到的组。
这种情况下,子查询的结果为4400、6000、
2500、4200、7000、17000和8300。
外部查询将采用这些结果,并在其WHERE子句中使用它们。
该WHERE子句包含一个等于(=)运算符,该运算符是一个只需要一个值的单行比较运算符。
=运算符无法接受子查询中的多个值,因此产生了错误。
要更正此错误,请将=运算符更改为IN。
∙内部查询没有返回任何行
因为没有名为“Haas”的雇员,所以子查询没有返回任何行。
hr@TEST0924>SELECTlast_name,job_idFROMemployees
2 WHEREjob_id=
3 (SELECTjob_idFROMemployeesWHERElast_name='Haas');
norowsselected
子查询的另外常见问题是内部查询没有返回任何行。
在示例的SQL语句中,子查询包含一个WHERE子句。
据推测,该语句的目的是要查找名为Haas的雇员。
该语句正确,但是因为没有名为“Haas”的雇员,所以执行时没有选择任何行。
因此,子查询不会返回任何行。
外部查询采用子查询的结果(空值),并在其WHERE子句中使用这些结果。
外部查询没有找到职务ID等于空值的雇员,因此不会返回任何行。
即使存在值为空的职务,也不会返回行,因为两个空值的比较会产生一个空值,从而使WHERE条件不为“真”。
∙多行子查询
•返回多个行
•使用多行比较运算符
返回多行的子查询被称为多行子查询。
应对多行子查询使用多行运算符,而不是使用单行运算符。
多行运算符需要一个或多个值:
SELECTlast_name,salary,department_id FROMemployees
WHEREsalaryIN
(SELECTMIN(salary) FROMemployees GROUPBYdepartment_id);
示例:
查找其薪金等于各个部门最低薪金的雇员。
先执行内部查询,生成一个查询结果。
然后可以处理主查询块,使用内部查询返回的值完善其搜索条件。
事实上,主查询将以下面的形式出现在OracleServer上:
SELECTlast_name,salary,department_id FROMemployees
WHEREsalaryIN(2500,4200,4400,6000,7000,8300,8600,17000);
∙在多行子查询中使用ANY运算符
SELECTemployee_id,last_name,job_id,salary FROMemployees
WHEREsalary (SELECTsalary FROMemployees WHEREjob_id='IT_PROG') ANDjob_id<>'IT_PROG'; ANY运算符(及其同义词SOME运算符)用于将某个值与子查询返回的每个值进行比较。 示例显示不是IT程序员且薪金低于任一IT程序员的雇员。 程序员的最高薪金为$9,000。 • •>ANY表示高于最低值。 •=ANY等同于IN。 参考: ∙在多行子查询中使用ALL运算符 SELECTemployee_id,last_name,job_id,salary FROMemployees WHEREsalary (SELECTsalary FROMemployees WHEREjob_id='IT_PROG') ANDjob_id<>'IT_PROG'; 在多行子查询中使用ALL运算符 ALL运算符用于将某个值与子查询返回的每个值进行比较。 示例显示薪金低于职务ID为IT_PROG的任何雇员的薪金且职务不是IT_PROG的雇员。 >ALL表示大于最高值, 而 NOT运算符可以与IN、ANY和ALL运算符一起使用。 参考: 使用EXISTS运算符 SELECT*FROMdepartments WHERENOTEXISTS (SELECT*FROMemployees WHEREemployees.department_id=departments.department_id); 使用EXISTS运算符 在查询中使用EXISTS运算符,查询结果取决于某些行是否在表中存在。 如果子查询至少返回一行,则求值结果为TRUE。 示例显示没有雇员的部门。 对于DEPARTMENTS表中每一行,检查条件,看一看在EMPLOYEES表中是否存在具有相同部门ID的行。 如果不存在这样的行,则相应 行满足条件,从而选择该行。 如果EMPLOYEES表中存在相应行,则不选择该行。 ∙子查询中的空值 SELECTemp.last_name FROMemployeesemp WHEREemp.employee_idNOTIN (SELECTmgr.manager_id FROMemployeesmgr); 示例中的SQL语句尝试显示没有任何下属的所有雇员。 逻辑上,此SQL语句应该返回12行。 但是,该SQL语句没有返回任何行。 因为内部查询返回的值中有一个为空值,所以整个查询不会返回任何行。 原因是所有条件与空值进行比较后都会产生一个空值。 因此,只要子查询的结果集中可能包含空值,就不要使用NOTIN运算符。 NOTIN运算符等同于<>ALL。 请注意,如果使用的是IN运算符,则子查询的结果集中存在空值就不会成为问题。 IN运算符等同于=ANY。 例如,要显示具有下属的雇员,可以使用下面的SQL语句: SELECTemp.last_name FROMemployeesemp WHEREemp.employee_idIN (SELECTmgr.manager_id FROMemployeesmgr); 另外,可以在子查询中包括WHERE子句,用来显示没有下属的所有雇员: SELECTlast_nameFROMemployees WHEREemployee_idNOTIN (SELECTmanager_id FROMemployees WHEREmanager_idISNOTNULL); ∙小结 子查询是一个SELECT语句,它嵌入到另一个SQL语句的子句中。 当查询基于带有未知中间值的搜索标准时,使用子查询非常有帮助。 子查询具有以下特性: •可以将一行数据传递给包含单行运算符(如=、<>、>、>=、<或<=)的主语句 •可以将多行数据传递给包含多行运算符(如IN)的主语句 •OracleServer先处理子查询,随后WHERE或HAVING子句会使用生成的结果 •可以包含组函数
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Oracle DB 使用子查询来解决查询 使用 查询 解决
![提示](https://static.bdocx.com/images/bang_tan.gif)