(三)Oracle分组函数

学习内容

组函数

函数

分类 作用
单值函数 对一个值、或者一个列进行操作,返回一个结果
分组函数 先分组,然后对每一组进行操作,每一组数据操作后分别得到一个结果

分组函数

组函数(分组函数),是指将数据按照某列的值进行分组后,然后使用组函数分别对每个分好的小组中的数据进行处理。所以组函数一般要结合着分组关键字group来使用。

统计分析(分组主要为了统计)

  • 分组 group by…

  • 函数 avg…

  • 筛选(与where类似) having…

  • 组函数

    avg求平均值
    count 计算有多少条数据
    max 最大值
    min 最小值
    sum 求和

    不常用:
    stddev 标准差
    variance 方差

  • 语句执行顺序
    where–>group by分组–>执行组函数–>having筛选->order by

  • 组函数可以出现的位置
    1) select后面
    2) having后面
    3) order by后面
    4) where后面一定【不能】出现组函数(因为where执行时组函数还未执行)

  • where与having最大的区别:(与静态非静态很像)
    where后面拿不到组函数执行结果,having可以。

注意:如果select/having语句后面出现了组函数,那么select/having后面没有被组函数修饰的列,就必须出现在group by 后面。

where和having对比

  1. where和having都是做条件筛选的
  2. where执行的时间比having要早
  3. where后面不能出现组函数
  4. having后面可以出现组函数
  5. where语句要紧跟from后面
  6. having语句要紧跟group by后面

group by和having的关系(与if else很像)

  1. group by可以单独存在,后面可以不出现having语句
  2. having不能单独存在,有需要的话,必须出现在group by后面

order by语句

  1. 如果sql语句中需要排序,那么就一定要写在sql语句的最后面
  2. order by后也可以出现组函数

使用分组函数

不结合group分组使用

注:如果不使用group分组的话,那么默认当前查询到的所有数据是一组。

avg():查询s_emp表中所有员工的平均工资

select avg(salary)
from s_emp;

(三)Oracle分组函数_第1张图片

count():查询s_emp表中共有多少条数据

select count(*)
from s_emp;

(三)Oracle分组函数_第2张图片

max():查询s_emp表中所有员工中的最大工资

select max(salary)
from s_emp;

(三)Oracle分组函数_第3张图片

min():查询s_emp表中所有员工中的最小工资

select min(salary)
from s_emp;

(三)Oracle分组函数_第4张图片

sum():查询s_emp表中所有员工的工资总和

select sum(salary)
from s_emp;

(三)Oracle分组函数_第5张图片

stddev():查询s_emp表中所有员工的工资的标准差

select stddev(salary)
from s_emp;

(三)Oracle分组函数_第6张图片

variance():查询s_emp表中所有员工的工资的方差

select variance(salary)
from s_emp;

结合group分组使用

avg():查询s_emp表中每个部门的平均工资

select dept_id,avg(salary)
from s_emp
group by dept_id;

(三)Oracle分组函数_第7张图片排序:
(三)Oracle分组函数_第8张图片

max():查询s_emp表中每个部门员工的最高工资

		select dept_id,max(salary)
		from s_emp
		group by dept_id;

(三)Oracle分组函数_第9张图片

sum():查询s_emp表中每个部门员工的工资总和

		select dept_id,sum(salary)
		from s_emp
		group by dept_id;

(三)Oracle分组函数_第10张图片

count():查询s_emp表中每个部门员工的人数

		select dept_id,count(*)
		from s_emp
		group by dept_id;

(三)Oracle分组函数_第11张图片

分组之后使用各种组函数

select dept_id,count(*),min(salary),max(salary),sum(salary),avg(salary)
from s_emp
group by dept_id;

(三)Oracle分组函数_第12张图片

结合group分组以及having筛选使用

avg():查询s_emp表中部门的平均工资大于等于1400的部门

		select dept_id,avg(salary)
		from s_emp
		group by dept_id
		having avg(salary)>=1400;

(三)Oracle分组函数_第13张图片

  • 思考:上面的sql语句修改为如下,是否可以?
		select dept_id,avg(salary)
		from s_emp
		where avg(salary)>=1400
		group by dept_id;

答:不可以。where后面不能出现分组函数。

sum():查询s_emp表中部门的总工资大于等于4000的部门

		select dept_id,sum(salary)
		from s_emp
		group by dept_id
		having sum(salary)>=4000;

(三)Oracle分组函数_第14张图片

其他实例

查询s_emp表中部门的平均工资大于等于1400的部门,并且显示出这些部门的名字,同时按照部门编号进行排序

  1. 第一步:查询出基本需求
    	select 
    		dept_id,avg(salary)
    	from 
    		s_emp
    	group by 
    		dept_id
    	having 
    		avg(salary)>=1400
    	order by 
    		dept_id;
    

(三)Oracle分组函数_第15张图片

  1. 第二步:加入多表查询,并且分别给表起别名
		select 
			se.dept_id,avg(se.salary)
		from 
			s_emp se,s_dept sd
		group by 
			se.dept_id
		having 
			avg(se.salary)>=1400
		order by 
			se.dept_id;
  1. 第三步:查询出s_dept表中的部门名称,并且进行等值连接
		select 
			se.dept_id,avg(se.salary),sd.name
		from 
			s_emp se,s_dept sd
		where 
			se.dept_id = sd.id
		group by 
			se.dept_id
		having 
			avg(se.salary)>=1400;
		order by 
			se.dept_id;
  1. 第四步:select语句后出现了组函数,那么没有被组函数修饰的列放到group by分组后面
		select 
			se.dept_id,avg(se.salary),sd.name
		from 
			s_emp se,s_dept sd
		where 
			se.dept_id = sd.id
		group by 
			se.dept_id,sd.name
		having 
			avg(se.salary)>=1400
		order by 
			se.dept_id;

(三)Oracle分组函数_第16张图片

  • 思考:是否可以把where后的条件筛选 转移 到having语句后面?
    答:可以。将where后面的筛选语句转移到having后面,效果相同。但是能写到where后面的条件就写到where后面。先筛选再操作数据效率高。
    (三)Oracle分组函数_第17张图片

查询s_emp表中最大的工资数,并且显示出这个最大工资的员工的名字

第一步:查出最大工资数

		select 
			max(salary)
		from 
			s_emp;

第二步:加上last_name的显示

		select 
			last_name,max(salary)
		from 
			s_emp;

第三步:select后面出现组函数,没有被组函数修饰的列放到group by后面,但是发现查询结果并不是想要结果

		select 
			last_name,max(salary)
		from 
			s_emp
		group 
			by last_name;

第四步:修改为多表查询(起别名),从s1表中查询出最大的工资数是多少,然后再和s2表连接起来,选出s2表中这个最大工资数的员工名字

		select 
			s2.last_name,max(s1.salary)
		from 
			s_emp s1,s_emp s2
		where 
			s2.salary = max(s1.salary)
		group by 
			s2.last_name;

第五步:where后面不能出现组函数,所以改为having

		select 
			s2.last_name,max(s1.salary)
		from 
			s_emp s1,s_emp s2
		group by 
			s2.last_name,s2.salary
		having 
			s2.salary = max(s1.salary);

练习:

查询s_emp表每个部门的最大工资数,并且显示出这个最大工资的员工名字以及该部门的名字和该部门所属区域,并且使用部门编号进行排序

		//查询每个部门的最大工资
		select 
			max(salary),dept_id
		from 
			s_emp
		group by 
			dept_id;		
		
		//查询每个部门的最大工资,排序
		select 
			max(salary),dept_id
		from 
			s_emp
		group by 
			dept_id
		order by 
			dept_id;
				
		//显示出这个最大工资的员工名字
		
		select 
			max(s1.salary) ,s1.dept_id,s2.last_name
	
		from 
			s_emp s1,s_emp s2
		
		where 
			s2.dept_id=s1.dept_id
		
		group by 
			s1.dept_id,s2.last_name,s2.salary
	
		having  
			max(s1.salary)=s2.salary
		
		order by 
			s1.dept_id;
						
		//显示出这个最大工资的员工名字,显示部门名称、部门所在地区
		select 
			max(s1.salary) ,s1.dept_id,s2.last_name,d.name,r.name
	
		from 
			s_emp s1,s_emp s2,s_dept d, s_region r
	
		where 
			s2.dept_id=s1.dept_id 
			and s1.dept_id=d.id 
			and d.region_id=r.id
		
		group by 
			s1.dept_id,s2.last_name,s2.salary,d.name,r.name
		
		having  
			max(s1.salary)=s2.salary
		
		order by 
			s1.dept_id;

总结

今天学习了分组函数。

子查询

即一个select语句中嵌套了另外的一个或者多个select语句

查询工资比Smith工资高的员工信息
第一步:查询Smith的工资数

		select salary
		from s_emp
		where last_name='Smith';	
		
			SALARY
		----------
			   940

第二步:查询工资比940高的员工信息

		select last_name,salary
		from s_emp
		where salary>940;

第三步:把第二步中的数字940替换成第一步中的sql语句即可(注意格式)

		select last_name,salary
		from s_emp
		where salary>(
			select salary
			from s_emp
			where last_name='Smith'
		);

查询所有部门的平均工资

	select dept_id,avg(salary)
	from s_emp
	group by dept_id;
	
	   DEPT_ID AVG(SALARY)
	---------- -----------
			42  1081.66667
			43         900
			34        1160
			44        1050
			31        1400
			32        1490
			35        1450
			50        2025
			41      1247.5
			45        1089
			33        1515

	   DEPT_ID AVG(SALARY)
	---------- -----------
			10        1450

查询平均工资比1247.5高的部门编号

	select dept_id
	from s_emp
	group by dept_id
	having avg(salary)>1247.5;
	
	   DEPT_ID
	----------
			31
			32
			35
			50
			33
			10

查询平均工资比1247.5高的部门中员工信息

	select last_name,salary,dept_id
	from s_emp
	where dept_id in(10,31,32,33,35,50);

等价于

	select last_name,salary,dept_id
	from s_emp
	where dept_id in(
		select dept_id
		from s_emp
		group by dept_id
		having avg(salary)>1247.5
	);

查询平均工资比 41号部门的平均工资 高 的部门中员工的信息

	select avg(salary)
	from s_emp
	where dept_id=41;
	
	AVG(SALARY)
	-----------
		 1247.5

所以这个sql语句和1247.5是等价的,那么就可以将上面sql语句中的1247.5给替换了

	select last_name,salary,dept_id
	from s_emp
	where dept_id in(
		select dept_id
		from s_emp
		group by dept_id
		having avg(salary)>1247.5
	);

替换后为:

	select last_name,salary,dept_id
	from s_emp
	where dept_id in(
		select dept_id
		from s_emp
		group by dept_id
		having avg(salary)>(
			select avg(salary)
			from s_emp
			where dept_id=41
		)
	);

练习:

注意:(可以把子查询的结果作为一张表来使用)

  1. 查询平均工资比 41号部门的平均工资 高 的部门中员工的信息,并且显示出当前部门的平均工资

  2. 查询平均工资比 41号部门的平均工资 高的部门中员工的信息,并且显示出当前部门的平均工资,同时显示出部门的名字

  3. 查询员工信息,这些员工的工资要比自己所在部门的平均工资高

  4. 查询员工信息,这些员工的工资要比自己所在部门的平均工资高,同时显示部门的名称以及所在地区

  5. 查询工资比 Ngao所在部门平均工资 要高的员工信息,同时这个员工所在部门的平均工资 也要 比Ngao所在部门的平均工资要高

  6. 查询工资比 Ngao所在部门平均工资 要高的员工信息,同时这个员工所在部门的平均工资 也要 比Ngao所在部门的平均工资要高,显示当前部门的平均工资

  7. 查询工资比 Ngao所在部门平均工资 要高的员工信息,同时这个员工所在部门的平均工资 也要 比Ngao所在部门的平均工资要高,显示当前部门的平均工资以及部门的名字和所在地区

总结

今天学习了嵌套查询,简而言之就是把一个一个的sql语句套在一起。步骤就是先完成一个功能,再实现另一个功能,然后把它们套在一起就好了。需要头脑清晰,不然很容易出错。

你可能感兴趣的:(Oracle学习笔记)