/*
------------------内容回顾----------------------
--上周内容回顾
--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(列名)非空计数
*/
/*
----------------一、分组/聚合函数 ------------------
分组函数只能从一组的值中计算出一个汇总的信息
所以在以上给出的查询例题中,分组函数是将查询所获得满足条件的记录行为作为一组
并返回一个统计值
如果要想“对多个组分别进行统计汇总”
例如:分别计算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
)
;
/*
------------二、带条件的分组查询
利用"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
;
-- 三、分组强化练习题 --
--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
;
-----------------------------------------
/*
-- 1、创建一个新的表格
create table 表名(
列名1 数据类型 约束条件,
列名2 数据类型 约束条件,
...
列名n 数据类型 约束条件
);
-- 1.1 常用的数据类型:number、varchar2、char、date
*/
-- 1、创建一个表
create table user_info(
user_name varchar2(30),
user_sex char(3),
height number(5,2),
user_time date
);
-- 2、PLSQL用菜单信息创建一个表
-- 导航栏table --> 右键 新建 -- > 创建表格窗口 输入表名
-- --> 列 选项页 -- 填入列名 数据类型 等
-- --> 点击 应用报存按钮 生成表
select t.*,t.rowid from user_info t;
/*
二、约束条件
--1、唯一约束 unique
值不能重复,值唯一,但可以为空null
--2、非空约束 not null
值不能为空null,但是一个列的值的默认值是可以为空的
--3、主键 primary key
常用于唯一标识,一个表中只需要有一个主键key
--4、检查约束 check
检查值是否满足某个条件,属于表对象,必须要有名字
--5、外键 references
也属于表对象,必须要有名字 主从表
--6、默认值 default
当暮云给列指定一个值的时候,该列的值默认为default定义的值,若没有default指定默认值,则是null
--7、添加注释
-- 7.1 表注释
comment on table 表名 is '注释内容'
-- 7.2 列注释
comment on column 表名.字段 is '用户名'
-- 7.3 删除其注释信息,只需要在 is后设置空字符串即可
*/
-- 2.1 创建一个有约束的表
create table user_info3(
user_id number(8) primary key, -- id 主键约束
user_name varchar2(30) not null, -- 非空约束
user_sex char(3) default '男' check(user_sex='男' or user_sex = '女'), -- 默认值,检查约束
height number(5,2) check(height>0),
user_time date default sysdate -- 默认为系统时间
);
-- 2.2 给info3的表添加注释信息
comment on table user_info3 is '用户信息表user_info3';
-- 2.3 给列添加注释信息
comment on column user_info3.user_id is '用户编号';
-- 2.4 删除表注释信息
-- 2.5 数据字典表
select * from user_col_comments; -- 列的注释信息
select * from user_tab_comments; -- 表的注释信息
select * from user_tables; -- 表在系统中存储的信息
/*
三、外键约束 主从表
作用:保持主从表的数据一致性
*/
-- 3.1 新建主表 班级表
create table class1(
clsno varchar2(20) primary key,
clsname varchar2(30) not null unique,
bz varchar2(20)
);
-- 3.2 新建从表 学生表
create table student1(
sno varchar2(20) primary key,
sname varchar2(30) not null,
ssex char(3) default '男' check(ssex='男' or ssex='女'),
sage number(3) check(sage>=6),
bir date,
clsno varchar2(20) references class1(clsno) -- 每个学生都有一个班级,外键连接的是主表的class1(clsno)列
);
-- 3.3 往class1和student填数据
select c.*,c.rowid from class1 c;
select t.*,t.rowid from student1 t;
/*
四、表练习
*/
-- 练习一、
-- 1、创建 student001表 学生表
create table student001(
sno varchar2(3) not null primary key,
sname varchar2(4) not null,
ssex varchar(2) not null,
sbirthday date,
class varchar2(5) not null+2
);
-- 2、创建course表
create table course001(
cno varchar2(5) not null primary key,
cname varchar2(10) not null,
tno varchar(10) not null references student001(sno)
);
-- 3、创建teacher教师表
create table teacher001(
tnp varchar(10) primary key,
tname varchar2(20)
);
-- 4、创建 score表
create table score001(
sno varchar2(3) not null references teacher001(tnp),
cno varchar2(5) not null references course001(cno),
degree number(10,1) not null
);
-- 练习二
---主表:
create table sxb0828(
ssno char(6) primary key,
stel number(7) not null check(stel between 6330000 and 6339999)
);
---从表:
create table stu0828(
sno char(6) primary key,
sname varchar2(30) not null,
ssex char(3) check(ssex='男' or ssex='女'),
sage number(3) check(sage >0),
mz varchar2(30) default '汉族' not null ,
cardid varchar2(18) not null unique,
ssno char(6) not null references sxb0828(ssno)
);
--建表先建主表再建从表,删除表时先删除从表再删主表