GroupBy子句的简单使用

--数据库基本表的创建,插入,删除,更新操作
--建立一个"学生"表
--学生的学号:Sno,类型是char(9)-->因为学生的学号是9位的定长的字符串;
--学生的姓名:Sname,类型是varchar2(8)-->因此可以是2,3,4汉字,而本数据库中一个汉字对应两个字符;
--学生的年龄:Sage,类型是smallint-->smallint占用的是两个字节,表示数的范围是,-32,768-->32,767;
--学生的性别:Ssex,类型是char(2)-->学生的性别只有两种情况,'男'或者'女',因此使用2位的定长字符串表示;
--学生的所属系别:Sdept,类型是varchar2(4)-->学生所属系别的长度是不确定的,假设最长4个字符;
--学生表的主键为学生的学号;
create table Student
(
       Sno char(9) primary key,
       Sname varchar2(8),
       Ssex char(2) not null,
       Sage smallint not null,
       Sdept varchar2(4) not null
);

--创建学生"课程"表
--课程的课程号:Cno,类型是char-->假设课程号是4位的定长字符;
--课程的课程名:Cname,类型是varchar2-->首先课程的名字是一个字符串,假设课程名字最多有10个汉字,最多含有20个字符组成;
--课程的先行课程号:Cpno,类型是char-->这个属性的数据类型应该和课程号的数据类型是一致的;
--课程的学分:Ccredit,类型为smallint-->课程的学分是一个小正整数;
--学生"课程"表中的主键是Cno;
--学生"课程"表中的外键为Cpno;课程表中的Cpno引用自课程表中的Cno;
create table Course
(
       Cno char(4) primary key,
       Cname varchar2(20) not null,
       Cpno char(4),
       Ccredit smallint not null,
       foreign key(Cpno) references Course(Cno)
);

--创建学生"选修"表
--学生的学号Sno,类型为char(9)-->学号的长度是9个数字的定长字符;
--学生的课程号Cno,类型为char(4)-->课程号的长度是4个数字的定长字符;
--学生的成绩Grade,类型为smallint-->这个整数在0->100之间的数字;
--选修表的主键:Cno和Sno的组合;
--选修表的外键:选修表中的Sno引用自学生表Student中的学号Sno;选修表中的Cno引用自学生表Courses中的课程号Cno;
create table SC
(
       Sno char(9),
       Cno char(4),
       Grade smallint,
       primary key(Sno,Cno),
       foreign key(Sno) references Student(Sno),
       foreign key(Cno) references Course(Cno)
);

--查询到当前数据库的字符集,
--如果value=ZHS16GBK,那么一个汉字占用2个字节,即一个汉字占用2个字符的大小;
--如果value=AL32UTF8,那么一个汉字占用3个字节,即一个汉字占用3个字符的大小;
select * from v$nls_parameters t where t.PARAMETER='NLS_CHARACTERSET';
alter user scott account unlock;
alter user sys account unlock;
alteruseruser_name account unlock identifiedby  new_password;
--查询的结果显示的value = ZHS16GBK,那就说明在本数据库中一个汉字是占用两个字节的.

--向学生表中插入数据
insert into Student values('201215121','李勇','男',20,'CS');
insert into Student values('201215122','刘晨','女',19,'CS');
insert into Student values('201215123','王敏','女',18,'MA');
insert into Student values('201215125','张立','男',19,'IS');

--违背实体的完整性
insert into Student values('201215121','李白','男',20,'CS');
insert into Student values('201215122','刘备','女',19,'CS');

--违背实体的完整性
insert into Student values(null,'张三','男',19,'CS');
insert into Student values(null,'李四','男',20,'IS');

--违背用户定义的完整性
insert into Student values('201215126','张立','男',null,'IS');
insert into Student values('201215126','张立',null,30,'IS');

--查询学生的全部信息
select * from Student;

--删除学生表
drop table Student;

--向课程表中插入数据
--注意插入数据时,可能会发生违背参照的完整性-->因为Cpno字段的值可能在表中还没有被插入;
--注意插入数据式,还可能发生违背实体的完整性-->因为我们插入了一行之后,再次插入,主码和表中的重复;
insert into Course values('2','数学',null,2);
insert into Course values('6','数据处理',null,2);
insert into Course values('4','操作系统','6',3);
insert into Course values('7','PASCAl语言','6',4);
insert into Course values('5','数据结构','7',4);
insert into Course values('1','数据库','5',4);
insert into Course values('3','信息系统','1',4);

--违背了实体的完整性约束
insert into Course values('1','数据库','5',5);
insert into Course values('3','信息系统','1',4);

--违背了实体的完整性
insert into Course values(null,'数据库','5',4);
insert into Course values(null,'数据结构','7',4);

--违背了参照的完整性
insert into Course values('8','数据结构','20',4);
insert into Course values('9','数据结构','11',4);

--违背了用户自定义完整性
insert into Course values('10','数据结构','7',null);
insert into Course values('13','操作系统','6',null);

--说明在不违背子表中外码的值来自父表中主码已有的值的前提下,外码的值可以为空
insert into Course values('2','数学',null,2);
insert into Course values('6','数据处理',null,2);

--对课程表进行的查询操作
select * from Course;

--删除课程表
drop table Course;

--向选修表中插入数据
--在对选修表中的数据进行插入的时候,插入的学号和插入的课程号必须是学生表中,课程表中已经出现的值;
--选修表中的主码是学号和课程号的的组合,这时候对单一的学号或者单一的课程号来看他们是可以重复的;
--在进行数据的插入的时候组成主码的一个或者多个属性列,都不能为空
insert into SC values('201215121','1',92);
insert into SC values('201215121','2',85);
insert into SC values('201215121','3',88);
insert into SC values('201215122','2',90);
insert into SC values('201215122','3',80);

--insert into SC values('201215122','1',90);

--违反参照的完整新,子表中外码的值不能是父表中主码中不存在的值
insert into SC values('201215122','9',100);
insert into SC values('201400644','1',70); 

--违背了实体的完整性,表中的主码的值必须是唯一的,不能够重复
insert into SC values('201215122','3',90);
insert into SC values('201215121','1',92);

--违背实体的完整性,组成主码的各个属性列的值不能为空
insert into SC values('201215122',null,90);
insert into SC values(null,'2',70);   

--对选修表进行的查询操作
select * from SC;     

--删除选修表基本表
drop table SC;
--group by 子句将查询结果进行按照一列或者多列的值进行分组,值相等的为一组
--对查询结果进行分组的目的是为了进一步细化聚集函数的作用对象.
--如果未对查查询结果进行分组,那么聚集函数将作用于整个查询结果,
--分组后聚集函数将作用在每一个组上,即每一个组都有一个函数值

--求各个课程号及选课的人数
--该语句对从select Cno from SC表中查询到的结果按照课程号相同条件进行分组,分组后每个课程号可能对应多个
--学生,这时候在对分组之后的结果作用聚集函数,统计每个课程号对应的课程选课的人数是多少,作用的对象是组
--即每组都会产生一个函数值.
select Cno
from SC;

select Cno,count(*)
from SC
group by Cno;

select Cno,count(Cno)
from SC
group by Cno;

select Cno,count(Sno)
from SC
group by Cno;

--如果未对结果进行分组,使用聚集函数,这样聚集函数的作用对象是整个数据来源的基本表
select count(*)
from SC;

--这样显然也是不可以的,Cno在SC表中可能有多个值,但是count(*)是对表中的某个属性列进行聚集,形成单值
select Cno,count(*)
from SC;

--如果分组之后还需要对分组的结果进行筛选(过滤),最终只输出满足条件的组,这时候可以使用having短语来指定
--筛选条件
--查询选修了三门以上(包含)课程的学生学号

--首先应该确定每个学生(每个学号)选修了多少门课程
select Sno,count(*)
from SC
group by Sno;

--查询选修表的全部信息
select *
from SC;

--将对上面的结果进行再次筛选(过滤),选择选修课程数大于等于3门的学生学号
select Sno
from SC
group by Sno
having count(*)>=3;

--该语句的执行过程是:首先SC表中的数据按照学生学号Sno进行分组,Sno相同的元组分到同一组中
--然后执行having子句的时候,先对分组后的每一组作用聚集函数count(*),统计出每个学生选修课程的数量
--最后对执行筛选条件,当一个学生选修的课程数是3门及3门以上的时候才会输出该学生的学号(没有就只输出Sno)
select Sno
from SC
group by Sno
having count(*)>3;

--where子句和having子句的区别在哪里
--where子句和having子句作用的对象不同,where子句是对整个基本表或者视图进行筛选(过滤),选出满足条件的元组
--having子句同样可以进行筛选,但是having子句的作用对象是分组之后的每一个组,选出满足条件的组的信息;
--where子句中是不能能使用聚集函数作为条件表达式的
select Sno
from SC
group by Sno
where count(*)>3;

--查询出平均成绩大于或者等于90分的学生学号和成绩
--这里的平均成绩指的是每个学生选修的所有课程的平均成绩
--首先对学号(学号相同的元组分为一组)进行分组,确定每个学生(学生学号)选修的各个课程成绩,
select Sno
from SC
group by Sno;
--然后对分组后的每一个组作用聚集函数avg(Grade)
select Sno 学生学号,avg(Grade) 平均成绩
from SC
group by Sno;
--最后将分组后作用聚集函数的分组统计结果进行筛选,选择出满足条件的组的信息
--在对最后的结果进行投影(选出我们需要看到的字段的时候),我们可以使用[as] 字段名对字段起别名
select Sno 学生学号,avg(Grade) 平均成绩
from SC
group by Sno
having avg(Grade)>90;

select Sno as 学生学号,avg(Grade) as 平均成绩
from SC
group by Sno
having avg(Grade)>80;

--如果使用where子句对作用聚集函数之后的分组进行筛选:where子句中是不能使用聚集函数作为条件表达式的
select Sno,avg(Grade)
from SC
group by Sno
where avg(Grade)>80;

--对分组后结果进行投影的时候,select子句之后能出现分组后每个组的整体信息,而不能出现分组前的详细信息
--错误提示不是Group by表达式
select Cno
from SC
group by Sno;

select Grade
from SC
group by Sno;

select *
from SC
group by Sno;

你可能感兴趣的:(Oracle)