Oracle-day4:分组查询(带条件)、DDL建表、约束、主从表

一、内容回顾

/*
  ------------------内容回顾----------------------
  --上周内容回顾
  --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
;

-----------------------------------------

一、DDL创建普通表

/*
  -- 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) 
 );
 --建表先建主表再建从表,删除表时先删除从表再删主表 



你可能感兴趣的:(数据库)