子查询是将多个SELECT语句变为一个的技术之一。子查询的输出可作为另一SELECT语句的输入。

定义子查询

子查询是嵌套到SELECT, INSERT, UPDATE,DELETE或其它子查询中的查询。
子查询可返回一行或多行,前者称为scalar 子查询。
子查询可用在:

  • SELECT列表
  • FROM子句
  • WHERE子句
  • HAVING子句

子查询也称为inner查询。使用inner查询的查询称为outer查询或父查询,Oracle对子查询嵌套层级为255层。
示例:

-- SELECT 列表
orclpdb1> SELECT sysdate Today, (select count(*) from departments) Dept_count from dual;TODAY     DEPT_COUNT
--------- ----------
13-OCT-19         27-- WHERE 子句
orclpdb1> select last_name from employees where (employee_id in (select manager_id from employees));LAST_NAME
----------------
Cambrault
De Haan
Errazuriz
Fripp
Greenberg
Hartstein
Higgins
Hunold
Kaufling
King
Kochhar
Mourgos
Partners
Raphaely
Russell
Vollman
Weiss
Zlotkey18 rows selected.-- FROM子句
orclpdb1> select max(salary), country_id from (select e.salary, department_id, location_id, l.country_id from employees e join departments d using (department_id) join locations l using (location_id)) group by country_id;MAX(SALARY) CO
----------- --10000 DE24000 US14000 UK13000 CA

子查询解决的问题

用于比较

例如找出小于平均工资的员工:

orclpdb1> select last_name from employees where salary < (select avg(salary) from employees);

另一个示例,找出有员工的部门:

orclpdb1> select department_name from departments where department_id in (select distinct(department_id) from employees);DEPARTMENT_NAME
------------------------------
Administration
Marketing
Purchasing
Human Resources
Shipping
IT
Public Relations
Sales
Executive
Finance
Accounting11 rows selected.

注意当子查询返回多行时,操作符也必须支持多行,如IN, NOT IN, ANY和ALL

Star Transformation

通常用于数据仓库。例如以下查询(SH Schema):

orclpdb1> select count(quantity_sold) from sales s, products p, customers c, channels ch where s.prod_id=p.prod_id and s.cust_id=c.cust_id and s.channel_id=ch.channel_id and p.prod_name='Comic Book Heroes' and c.cust_city='Oxford' and ch.channel_desc='Internet';COUNT(QUANTITY_SOLD)
--------------------9

可以改为Star Transformation:

orclpdb1> select count(quantity_sold) from sales where prod_id in (select prod_id from products where prod_name='Comic Book Heroes') and cust_id in (select cust_id from customers where cust_city='Oxford') and channel_id in (select channel_id from channels where channel_desc='Internet');COUNT(QUANTITY_SOLD)
--------------------9

Star Transformation执行效率更高,并且更易于维护。

生成用于select的表

例如:


orclpdb1> select avg(salary), country_id from (select salary, country_id from employees natural join departments natural join locations) group by country_id;AVG(SALARY) CO
----------- --5640 US8500 UK6000 CA

SELECT列表

用于Projection。

orclpdb1> select (select max(salary) from employees) * (select max(commission_pct) from employees) /100 from dual;(SELECTMAX(SALARY)FROMEMPLOYEES)*(SELECTMAX(COMMISSION_PCT)FROMEMPLOYEES)/100
-----------------------------------------------------------------------------96

生成传递给DML语句的结果集

例如:

insert into table_name select * from ...;
update table_name set col_name = (select avg(salary) from employees);
delete from table_name where col_name not in (select ...)

子查询类型

3种,单行,多行和相关子查询。

单行与多行子查询

单行子查询返回i一行,特例为scalar子查询,即一行和一列。
多行子查询返回多行,通常传递给SELECT和DML语句。
单行与多行子查询可用于父查询的WHERE和HAVING子句。但比较操作符有限制,以下为单行子查询的比较符:
=,>,>=,<,<=,<>,!=
以下为多行子查询的比较符:
IN, NOT IN, ALL, ANY

相关子查询

是指子查询引用了父查询中的列。

orclpdb1> select p.last_name, p.department_id
from employees p
where p.salary < (select avg(s.salary) from employees s where s.department_id=p.department_id);LAST_NAME                 DEPARTMENT_ID
------------------------- -------------
OConnell                             50
Grant                                50
Fay                                  20
Gietz                               110
Kochhar                              90
De Haan                              90
Austin                               60
Pataballa                            60
Lorentz                              60
Chen                                100
Sciarra                             100
Urman                               100
Popp                                100
Khoo                                 30
Baida                                30
Tobias                               30
Himuro                               30
Colmenares                           30
Nayer                                50
Mikkilineni                          50
Landry                               50
Markle                               50
Bissot                               50
Atkinson                             50
Marlow                               50
Olson                                50
Mallin                               50
Rogers                               50
Gee                                  50
Philtanker                           50
Stiles                               50
Seo                                  50
Patel                                50
Davies                               50
Matos                                50
Vargas                               50
Olsen                                80
Cambrault                            80
Tuvault                              80
Smith                                80
Doran                                80
Sewall                               80
Marvins                              80
Lee                                  80
Ande                                 80
Banda                                80
Smith                                80
Bates                                80
Kumar                                80
Hutton                               80
Taylor                               80
Livingston                           80
Johnson                              80
Taylor                               50
Fleaur                               50
Sullivan                             50
Geoni                                50
Dellinger                            50
Cabrio                               50
Gates                                50
Perkins                              50
McCain                               50
Jones                                50
Walsh                                50
Feeney                               5065 rows selected.

单行与多行子查询

先来看几个例子:

select last_name from employees where manager_id in
(select employee_id from employees where department_id in (select department_id from departments where location_id in(select location_id from locations where country_id='UK')));
-- 平均工作最高的工作
select job_title from jobs natural join employees group by job_title having avg(salary) =
(select max(avg(salary)) from employees group by job_id);
JOB_TITLE
-----------------------------------
President

ANY和ALL操作符很少用,因为有对应的Group函数,不过意义了解以下:

< ANY: 小于MAX
> ANY: 大于MIN
= ANY: 相当于IN
< ALL:小于MIN
> ALL:大于MAX
<> ALL:NOT IN

Exsits条件

-- 部门有人的
select department_name from departments d where exists
(select * from employees e where d.department_id = e.department_id)
-- 部门没人的
select department_name from departments d where not exists
(select * from employees e where d.department_id = e.department_id)

子查询中的Null结果

如果子查询中的结果集中有Null,那么父查询有可能返回Null。原因是与Null的比较与Null的比较返回Null。因此,如果子查询可能返回Null,就要避免用 Not In操作符。

-- 无结果,因为子查询中有空值
select last_name, employee_id, manager_id from employees where employee_id
not in (select manager_id from employees);-- 以上语句的改写
select last_name, employee_id, manager_id from employees where employee_id
not in (select manager_id from employees where manager_id is not null);-- 另一例子
select last_name, employee_id, manager_id from employees where employee_id
in (select manager_id from employees);

集合操作

是指将多个SELECT的结果集进行操作。包括:
UNION:合集,排序并去除重复
UNION ALL:合集,未排序,未去除重复。如果你知道集合中没有重复值,那就使用UNION ALL,因为UNION排序还是有开销的。
INTERSECT:交集,排序,去除重复
MINUS:差集,排序,去除重复。
以上所有排序都是升序。

集合与韦恩图(Venn Diagrams)

略。

集合操作基本原则

集合操作符没有优先级,从左至右评估。
集合的列名可以不一样,会采用第一个集合的列名。
集合的列数必须一样。
集合的数据类型可以不一样,但必须属于同一数据类型组。例如DATE和TIMESTAMP,INTEGER和NUMBER。结果会选用较高精度的那个,如TIMESTAMP和NUMBER。除数据类型组转换外,集合操作不会做任何隐式数据类型转换。
排序是基于所有列,从左到右。UNION ALL不排序。
例子:

select region_name from regions
union
select region_name from regions
REGION_NAME
-------------------------
Americas
Asia
Europe
Middle East and Africaselect region_name from regions
union all
select region_name from regions
REGION_NAME
-------------------------
Europe
Americas
Asia
Middle East and Africa
Europe
Americas
Asia
Middle East and Africa8 rows selected.

控制行返回的顺序

对于集合操作,可以加Order by,但只能针对整个集合操作的结果,并且只能加在最后。

OCA/OCP Oracle 数据库12c考试指南读书笔记:第11章: Subqueries and Set Operators相关推荐

  1. OCA/OCP Oracle 数据库12c考试指南读书笔记:第6章: DML and Concurrency

    DML语句 共5个: • SELECT • INSERT • UPDATE • DELETE • MERGE insert 可以插入一行,或多行.可以插入多张表. 可以指定值插入,可以从子查询结果集插 ...

  2. OCA/OCP Oracle 数据库12c考试指南读书笔记:第27章: Duplicating a Database

    可传输表空间可将表空间从一个数据库拷贝到另一数据库,而无需耗时的export/import. 可传输数据库是可传输表空间的扩展,可创建新数据库,并将非系统表空间拷贝到新数据库. 还可以复制整个数据库, ...

  3. OCA/OCP Oracle 数据库12c考试指南读书笔记:第17章: Moving and Re-organizing Data

    SQL*LOADER支持异构,DATA PUMP只支持Oracle数据库 移动数据的方式 SQL*LOADER,DATA PUMP和外部表. 创建和使用DIRECTORY 对象 Oracle DIRE ...

  4. OCA/OCP Oracle 数据库12c考试指南读书笔记:第3章: Installing Oracle Grid Infrastructure for a Stand-Alone Server

    Grid Infrastructure以下简称GI. GI是单独安装的,为数据库提供存储和高可用等服务. 对于单实例,GI是可选的,用于提供ASM存储服务和错误自动重启:对于RAC,GI是必需的. G ...

  5. OCA/OCP Oracle 数据库12c考试指南读书笔记:第20章: The Resource Manager

    为保证SLA,用户要区别对待,牺牲一批人以保障一些人. 配置数据库资源管理 Oracle的资源管理与大机类似,可以保证无论负载如何,用户都可以获得约定SLA的服务. 资源管理的配置是简单的,但测试其效 ...

  6. OCA/OCP Oracle 数据库12c考试指南读书笔记:第31章:Multitenant Container and Pluggable Database Architecture

    多租户选件将多个数据库整合为一个,但数据库仍可以独立管理和使用.对于用户和开发者改变不大,但DBA需要学习新东西. 多租户需要在企业版基础上额外购买多租户选件,否则只能使用non-CDB.但non-C ...

  7. OCA/OCP Oracle 数据库12c考试指南读书笔记:第15章: Oracle Storage

    表的行数据在块中的存储 在最底层,行存放于block中,之上还有其它层次. Oracle数据存储模式 segment是有类型的,是schema 对象,如表,索引等.一个segment只能位于一个表空间 ...

  8. “Oracle数据库并行执行”技术白皮书读书笔记

    本文为白皮书Parallel Execution with Oracle Database(2019年2月20日版本)的读书笔记. 简介 数据快速增长,但业务仍要求数据的快速处理. 并行执行是大规模数 ...

  9. PMP读书笔记(第11章)

    大家好,我是烤鸭:     今天做一个PMP的读书笔记. 第十一章 项目风险管理 项目风险管理 项目风险管理的核心概念 项目风险管理的趋势和新兴实践 裁剪考虑因素 在敏捷或适应型环境中需要考虑的因素 ...

最新文章

  1. 从输入字段读取属性时,HTML编码丢失
  2. python专业名词_python 术语
  3. yytextview多种格式_iOS YYText的使用笔记一(YYTextView图文编辑器)
  4. Windows Embedded CE 6.0开发初体验(一)Windows CE概述
  5. linux Pci字符驱动基本加载流程
  6. PHP文字转语音合成网源码 百度API开发
  7. 为什么有的安卓手机越用越慢,刷机也不行?
  8. Linux命令-关机命令详解
  9. 电赛模拟训练日志总结三(红外光通信装置)
  10. DOS窗口打开本地应用,打开chrome浏览器
  11. imdb导mysql_IMDB电影排行爬取分析
  12. 2018年DevOps最新现状研究报告解读
  13. linux samba 拒绝访问,Samba拒绝访问的解决方式
  14. Codeforces Round #531 F. Elongated Matrix (状压dp)
  15. 为什么梯度反方向是函数值下降最快的方向?
  16. kde 崩溃,如何重启 kde plasma 5 桌面
  17. lisp不是函授型语言_LISP语言
  18. LINUX关闭防火墙、开放特定端口等常用操作
  19. 熟知ghost参数 恢复系统没烦恼【xpghost】
  20. 关于孟岩一篇文章的讨论

热门文章

  1. oracle remap schema,【IMPDP】 实现不同用户之间的数据迁移——REMAP_SCHEMA参数
  2. 问题解决之 Win10下 word 文件和 ppt 文件打开时遇到错误
  3. 安卓手机可以拍摄证件照吗
  4. 携程AI和推荐系统的云化实践
  5. Codeforces1575 D. Divisible by Twenty-Five(dp)
  6. 【渝粤教育】 国家开放大学2020年春季 1332中文学科论文写作 参考试题
  7. RocketMQ4.0源码分析之-路由管理
  8. Unity角色扮演游戏集合
  9. 一文让你学会PC软件升级,学不会过来打我
  10. 报错:CMake Error at /usr/share/cmake-3.10/Modules/CMakeDetermineCCompiler.cmake:48 (message):