/*
------------------内容回顾----------------------
--上周内容回顾
--1、单表的基础查询
--A、
select * from emp;
--B、列的运算
--数字类型运算 + - * /
--函数运算 mod ceil floor round upper lower
--C、取别名--列、表达书取别名
--*表示所有的列和列同时存在时要写成:表名.*
--D、表取别名 用表名的地方要用别名替换
--E、条件筛选 where
--比较运算符 > >= < <= <> !=
--逻辑运算符 not > and > or
--between A and B 相当于 >=A and <=B
--日期的表示:date'日期格式字符串','两位天数-中文月份-4位年份',
--to_date('日期格式字符串','yyyy-mm-dd')
--日期的截取to_char(日期,'字符串') yyyy、mm、dd、yyyy-mm-dd
--F、in和 not in
--G、空值 is null、非空值 is not null
--H、条件判断 case when语句
--2、子查询查询要用圆括号括起来
--A、单行值子查询 比较运算符来连接
--B、多行值子查询 in或者not in 来连接
--C、from子查询 用查询取替换表 with as语句、rownum
--3、分组查询
--A、聚合函数 count(*) sum() avg() max() min()
--sum()非空求和
--avg() 非空求平均值
--count(列名)非空计数
*/
二、分组查询
sql复制代码
/*
----------------一、分组/聚合函数 ------------------
分组函数只能从一组的值中计算出一个汇总的信息
所以在以上给出的查询例题中,分组函数是将查询所获得满足条件的记录行为作为一组
并返回一个统计值
如果要想"对多个组分别进行统计汇总"
例如:分别计算emp表中每个部门职工的最低工资、最高工资、平均和总工资、
则是要在查询命令中使用到【 group by】子句
进行分组查询,Oracle会把查询到的行分成多个组,对于每一个组返回一个汇总信息
--------------分组查询的基本语法--------------------
select 字段名
from 表名
[where 过滤条件]
[group by 字段];
---------------
group by:一致性:在包括 group by 子句的查询中,select子句
后面的列名表中,除统计聚合函数以外,均应包含在:group by 子句中
即:列名表中除聚合函数外中不能出现 group by 分组子句,不存在的列名,否则出错
*/
-- 1、计算出公司支付给每个工种的总工资
-- 1.1
select job,sum(sal)
from emp
group by job -- 按照工种来分组
;
-- 2、统计各部门的人数、工资总和、平均工资
select deptno,count(deptno),sum(sal),avg(sal)
from emp
group by deptno
;
-- 3、(多列分组)计算每个部门中每个工种各有多少职工数
select deptno,job,count(*),count(emptno)
from emp
group by deptno,job
;
-- 3.1 带上排序,也是需要group by后面的列名
select deptno,job,count(*),count(empno)
from emp
group by deptno,job
order by deptno,job
;
-- 4、查询员工工资最低为其部门最低工资的员工的编号和姓名及工资
-- 4,1 找出每个部门的最低工资
select deptno,min(sal) minssal
from emp
group by deptno
;
-- 4.2 where 多行子查询
select *
from emp
where (deptno,sal) in(
select deptno,min(sal) minssal
from emp
group by deptno
)
;
三、带条件的分组查询
sql复制代码
/*
------------二、带条件的分组查询
利用"group by"子句将选择到的进行分组时,
可以使用 having子句用于限制选择的组(进一步筛选),
having子句的作用同where子句相似,都是指定查询条件。
不同的是where子句对行进行选择,检查每条记录是否满足条件,
而having子句是检查 分组之后的各组 是否满足条件。
having子句是配合group by子句使用,在没有"group by"子句时不能用,
并且group by和having子句在命令中要出现在where子句之后。
--------- 语法 ------------
select 字段/表达式
from 表名 where 单条记录的过滤条件
group by 字段
having 分组函数的比较表达式 对group by 分组后的结果进一步筛选 having后面不能使用别名 不能单独使用
order by 排序;
------where 和 having 他们的区别是什么? -------
--1. 先筛选再分组,用使用where筛选,速度上更快
--2. where在group by 之前使用的,having是在group by之后使用的
--3. where不能筛选聚合函数的结果,having可以
--4、当要求的条件是某个具体的单值条件(条件能在表中查询到)先用where条件筛选,如果是需要通过聚合函数计算得出
--的条件,先要用group by分组,然后再用having筛选。
*/
/*
-----------注意事项--------
1、分组函数只能出现在select、having、order by 子句中
2、如果在select语句同时含有group by、having、orderby,那么他们的顺序是group by、having、order by
3、group by 有一个原则,就是 select 后面的所有字段(除聚合函数外),必须出现在 group by 后面,否则,有语法错误(重要)
4、有having 一定有group by,having筛选时不能使用该查询的别名
*/
-- 1、查询各工种组的年平均工资,要求每个工种组至少在3人以上(统计3人以上的工种的年平均工资)
-- 1.1 先分组 group by:年平均工资=平均工资*12
select job,avg(sal),avg(sal)*12 yearsal,count(empno),count(*)
from emp
group by job
;
-- 1.2 在分组后进一步筛选:having + 聚合函数
select job,avg(sal),avg(sal)*12 yearsal,count(empno),count(*)
from emp
group by job
having count(empno) >= 3
;
-- 2、查询出至少有两名秘书CLERK的所有部门的部门号和人数,并按人数降序排序。
-- 2.1 先找出所有工种是:CLERK的记录
select * from emp where job = 'CLERK';
-- 2.2 对第一步结果进行分组
select deptno,count(*),count(empno)
from mep where job = 'CLERK'
group by deptno;
-- 2.3 对第二部进行having筛选
select deptno,count(empno) c1,count(*) c2,count(1) c3
from emp
where job = 'CLERK'
group by deptno
having count(empno) >= 2 -- having子句内不能用别名
;
-- 2.4 排序
select deptno,count(empno) c1,count(*) c2,count(1) c3
from emp
where job = 'CLERK'
group by deptno
having count(empno) >= 2 -- having子句内不能用别名
order by count(empno)
;
-- 3、查询出所有经理和销售人员的年平均工资,并按年平均工资降序排序。
-- 3.1 先找出所有的经理和销售员 where
select * from emp where job = 'MANAGER' or job = 'SALESMAN';
-- 3.2 对第一步的结果进行分组 group by
select job,avg(sal),avg(sal)*12 yearavg
from emp
where job in('MANAGER','SALESMAN')
group by job;
-- 3.3 排序 -- 排序可以用别名和表达式的
select job,avg(sal)*12 yearsal
from emp
where job in('MANAGER','SALESMAN')
group by job
order by yearsal desc
;
四、分组练习题
sql复制代码
-- 三、分组强化练习题 --
--1. 显示平均工资为>2000的职位
select job,avg(sal)
from emp
group by job
having avg(sal) > 2000
;
--2. 计算工资在2000以上,职位平均工资大于3000的职位及平均工资
select job,avg(sal)
from emp
where sal > 2000
group by job
having avg(sal) > 3000
;
--3. 找每个部门的最高和最低的工资
select deptno,max(sal),min(sal)
from emp
group by deptno
;
--4. 找每个部门中每种职位的最高和最低的工资
select deptno,job,max(sal),min(sal)
from emp
group by deptno,job
order by deptno,job
;
--5. 显示出工作名称(job)中包含"MAN"的平均工资,最高工资,最低工资及工资总和
select job,avg(sal),max(sal),min(sal)
from emp
where job like '%MAN%' -- 1、先找出包含MAN的记录
group by job
;
--6. 显示出20号部门的员工人数
select count(empno)
from emp
where deptno = 20
;
--7. 显示出平均工资大于2000的部门名称(及平均工资)
-- dept表
-- deptno 部门编号
-- dname 部门名称
-- loc 部门所在地
-- 7.1 先从emp表中查询到平均工资
select deptno,avg(sal) from emp
group by deptno having avg(sal) > 2000;
-- 7.2 子查询筛选
select * from dept
where deptno in(
select deptno
from emp
group by deptno
having avg(sal) > 2000
)
;
--8. 显示每个部门每种工种平均工资大于2500的部门及工种
select deptno,job,avg(sal)
from emp
group by deptno,job
having avg(sal) > 2500
;
--9. 显示出工种名称job中包含"MAN",并且平均工资大于1000的职位名称及平均工资
select job,avg(sal)
from emp
where job like '%MAN%'
group by job
having avg(sal) > 1000
;
--10. 列出最低工资大于1500的各种工种
select deptno,min(sal)
from emp
group by deptno
having min(sal) > 1500
;