SQL查询语句之子查询2

2、 ANY操作:一共分为三种形式:

◆ =ANY:功能与IN操作一样

查询 工资 与经理们的工资 相同的 所有雇员信息

SELECT * FROM emp

WHERE sal =ANY(

SELECT sal FROM emp WHERE job='MANAGER' ) ;

◆ >ANY:比 子查询返回的最小值 要大

查询工资比经理们之中的最低工资 要高的 所有雇员信息

SELECT * FROM emp

WHERE sal >ANY(

SELECT sal FROM emp WHERE job='MANAGER' ) ;

查询 工资 比经理们之中的最高工资 要低的 所有雇员信息

SELECT * FROM emp

WHERE sal

SELECT sal FROM emp WHERE job='MANAGER' ) ;

3、 ALL操作:一共分为两种形式:

◆ >ALL:比 子查询返回的最大值 要大

查询 工资 比经理们之中的最高工资 要高的 所有雇员信息

SELECT * FROM emp

WHERE sal >ALL(

SELECT sal FROM emp WHERE job='MANAGER' ) ;

查询 工资 比经理们之中的最低工资 要低的 所有雇员信息

SELECT * FROM emp

WHERE sal

SELECT sal FROM emp WHERE job='MANAGER' ) ;

在实际的开发之中,WHERE子句中,出现子查询的几率,是很高的。

【在HAVING子句里面使用子查询(次重点)】

如果子查询可以在HAVING子句里面出现,那么,只有一种情况,子查询返回的是单行单列数据,并且需要进行统计函数计算的时候。

范例:查询出高于公司平均工资的职位名称、职位人数、平均工资

◆ 找出公司的平均工资

SELECT AVG(sal) FROM emp ;

◆ 以上的查询返回的是单行单列,一般返回单行单列的数据,只会在WHERE或HAVING子句里面出现,但依据此题的要求,应该是在HAVING子句里面使用。

SELECT job, COUNT(empno), AVG(sal)

FROM emp

GROUP BY job

HAVING AVG(sal)>(

SELECT AVG(sal) FROM emp ) ;


在进行HAVING操作的过程之中,子查询返回的数据,不会过于的复杂。

【在SELECT子句里面使用子查询(了解)】

子查询可以出现在SELECT子句里面,只不过,大部分的开发者,如果不是万不得已的时候,绝对不会这么去做的。

范例:查询每个雇员的编号、姓名、职位、部门名称

◆ 如果,按照以前学习的多表查询,来做此题:

SELECT e.empno, e.ename, e.job, d.dname

FROM emp e, dept d

WHERE e.deptno=d.deptno ;

◆ 如果,在SELECT子句里面使用子查询,来做此题:

SELECT e.empno, e.ename, e.job,

( SELECT d.dname FROM dept d WHERE d.deptno=e.deptno )

FROM emp e ;

每当有一行emp的数据出现,那么,就要查询一次dept表,等于是你用户自己发出了一次的查询指令,

但是,却变为了“1+N”次查询,(如果emp表有100行数据,就会查询100次dept表),这种操作,一般不会有人去使用。

【在FROM子句里面使用子查询(重点)】

如果子查询返回的结构是多行多列的数据,那么,就相当于是一张临时表的形式,所以,可以直接在FROM子句里面使用,下面回顾一个原始的题目。

范例:查询出每个部门名称、位置、部门人数

◆ 之前,可以通过多表查询,而后,进行多字段分组实现:

SELECT d.dname, d.loc, COUNT(e.empno)

FROM emp e, dept d

WHERE e.deptno(+)=d.deptno

GROUP BY d.dname, d.loc ;

但是以上的功能,也可以使用子查询实现。

◆ 改善做法,利用子查询完成。

● 查询出部门的编号、名称、位置,此查询只需要dept一张表就够了。

SELECT d.deptno, d.dname, d.loc FROM dept d ;

● 统计出每个部门的编号、人数,此查询只需要emp一张表就够了。

SELECT deptno, COUNT(empno)

FROM emp GROUP BY deptno ;

● 通过以上的两个查询结果发现,可以在部门编号上,找到联系:

子查询 的列名称 不使用 别名 ( 会报错 )

SELECT d.dname, d.loc, temp.COUNT(empno)

FROM dept d, (

SELECT deptno, COUNT(empno)

FROM emp

GROUP BY deptno ) temp

WHERE d.deptno=temp.deptno(+) ;

子查询 的列名称 使用 别名

SELECT d.dname, d.loc, temp.count

FROM dept d, (

SELECT deptno, COUNT(empno) count

FROM emp

GROUP BY deptno ) temp

WHERE d.deptno=temp.deptno(+) ;

● 利用NVL( )函数,将null替换为0

SELECT d.dname, d.loc, NVL( temp.count , 0 )

FROM dept d, (

SELECT deptno, COUNT(empno) count

FROM emp

GROUP BY deptno ) temp

WHERE d.deptno=temp.deptno(+) ;

疑问? 发现多表查询也可以实现统计,子查询也能够实现统计,那么,哪种方式好呢?

为了可以更好的解释这个问题,假设将数据表中的数据扩大100倍,即:此时假设emp表有1400条记录,而dept表有400条记录。

◆ 使用多表查询及分组统计:

● emp表的1400条 × dept表的400条 = 560,000条记录

◆ 使用子查询:

● 子查询的数据量:只使用emp的1400条记录,最多返回400行统计结果。

(因为,子查询,是按照emp表中的部门编号deptno来进行分组统计的。

子查询,返回的是400个部门的部门编号,和每个部门所对应的雇员人数。

所以,子查询,返回的是400行记录。)

● 子查询的返回数据量400条 × dept表的400条 = 160,000条记录

● 两个操作,加在一起,最多只操作了:160,400条记录。

在实际的工作之中,子查询的主要目的是解决多表查询所带来的性能问题,所以,在开发之中,使用是最多的。

在编写代码的过程之中,我们很少直接去关注 多表查询,但是,我们都会关注 子查询,用 子查询 来改善 多表查询 所带来的 笛卡尔积 过多的问题。

在FROM子句出现子查询,一般还有一种情况:

“在整个查询语句之中,需要使用到统计函数,但是,又无法直接去使用统计函数的时候,可以先在FROM子句里面利用子查询实现统计”。

【总结】

复杂查询 = 简单查询 + 限定查询 + 多表查询 + 分组统计查询 + 子查询。

如果是子查询,首先考虑的一定是WHERE或FROM子句里面出现子查询的操作,像SELECT子句,几乎是可以忽略掉的,而HAVING子句出现子查询,只有在使用统计函数的时候,才会使用。

子查询,最大的作用是: 解决多表查询所带来的笛卡尔积影响的性能问题。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1. select * from emp; 2. select empno, ename, job from em...
    海纳百川_4d26阅读 1,938评论 0 4
  • 查询是数据的一个重要操作。用户发送查询请求,经编译软件变异成二进制文件供服务器查询,后返回查询结果集给用户,查询会...
    产品小正阅读 1,435评论 0 2
  • 幕课oracle学习笔记 --!!!scott用户 --一.分组查询 --1.常用的分组函数:AVG(平均数),S...
    xiaoxiao苏阅读 1,289评论 0 5
  • 1.简介 数据存储有哪些方式?电子表格,纸质文件,数据库。 那么究竟什么是关系型数据库? 目前对数据库的分类主要是...
    乔震阅读 1,776评论 0 2
  • “后来我思索了很久,在她眼里看来我像什么样子。” 这是书中主人公分手后感叹的一句话。 他和她在一起两年,不好也不坏...
    我愛一個幼稚鬼阅读 652评论 3 4