mysql综合小项目练习

一、创建表

-- 创建区域表 存储北京市的所有区县信息
create table area(
	a_id int(8) comment '地区ID',
	a_name varchar(32) comment '地区名称',
	constraint pk_area_a_id primary key(a_id)
);

-- 创建学校表 保存各区域的学校信息
create table school(
	sc_id int(8) comment '学校表的主键ID',
	sc_name varchar(32) comment '学校名称',
	a_id int(8) comment '所属区域外键',
	constraint pk_student_sc_id primary key(sc_id)
);

-- 创建学生表 存储学生信息
create table student(
	s_id int(8) comment '学生编号',
	s_name varchar(32) comment '学生姓名',
	s_sex int(1) comment '性别 0(女) 1(男)',
	s_birthday date,
	s_examnum varchar(32),
	sc_id int(8),
	constraint pk_student_s_id primary key(s_id)
);

-- 创建考试科目表 考试科目 一共有四个 1: 语文  2: 数学 3: 英语  4 : 综合
create table `subject`(
	su_id int(8) comment '学科ID',
	su_name varchar(32) comment '学科名称',
	constraint pk_subject_su_id primary key(su_id)
);

-- 创建考试成绩表 保存考试成绩
create table result(
	r_id int(8) comment '考试成绩',
	su_id int(8) comment '学科ID',
	s_id int(8),
	r_score int(8) comment '考试分数',
	constraint pk_result_r_id primary key(r_id)
);

表关系说明 :

  • 一个地区有多个学校,所以地区表和学校表是一对多关系
  • 一个学校有多个学生,所以学校表和学生表是一对多关系
  • 一个学生有多个考试结果,所以学生表和考试成绩表是一对多关系
  • 一个考试科目下有多个考试成绩,所以考试科目表和考试成绩表示一对多关系

建立外键约束:

alter table school add constraint fk_area_school_a_id foreign key(a_id) references area(a_id);
alter table student add constraint fk_school_student_sc_id foreign key(sc_id) references school(sc_id);
alter table result add constraint fk_student_result_s_id foreign key(s_id) references student(s_id);
alter table result add constraint fk_subject_result_su_id foreign key(su_id) references `subject`(su_id);

二、查询各表数据的基本情况

-- 1. 查询地区表数据
select * from area;

-- 2. 查询学校表数据
select * from school;

-- 3. 查询学生表数据
select * from student;

-- 4. 查询学科表数据
select * from `subject`;

-- 5. 查询考试成绩表数据
select * from result;

三、查询各表数据的数据总量

-- 1. 查询地区表数据
select count(1) from area;

-- 2. 查询学校表数据
select count(1) from school;

-- 3. 查询学生表数据
select count(1) from student;

-- 4. 查询学科表数据
select count(1) from `subject`;

-- 5. 查询考试成绩表数据
select count(1) from result;

四、分页查询数据

格式:limit [偏移量],行数
想完成一个分页:

  • 总数据量 总条数 totalCount
  • 每页展示的数据量 页容量 pageSize
  • 一共有多少页 总页数 totalPage
  • 当前页数 页码 pageIndex

总结:

  1. totalPage = totalCount%pageSize==0? totalCount/pageSize: totalCount/pageSize+1;
  2. limit的第一个参数 = (pageIndex-1)*pageSize;
  3. limit的第二个参数 = pageSize;
-- 1. 查询前五条学生数据
select * from student limit 5;

-- 2. 查询第6-10条学生数据
select * from student limit 5,5;

-- 3. 查询第11-15条学生数据
select * from student limit 10,5;

-- 4. 查询第16-20条学生数据
select * from studnet limit 15, 5;

五、多表连接查询

-- 1. 查询每个地区的学校信息
select a.a_name, sc.* from area a join school sc on a.a_id = sc.a_id;

-- 2. 分页查询所有学生的基本信息以及所属院校和所属地区 分页展示 每页10条 展示第1页
select s.*, sc.sc_name, a.a_name
from student s join school sc on s.sc_id = sc.sc_id
join area a on a.a_id = sc.sc_id
limit 10;

-- 3. 查询语文考试的前十名成绩
select r.s_id,su.su_name, r.r_score
from result r join `subject` su on su.su_id = r.su_id
where su.su_name = '语文'
order by r.r_score desc
limit 10;

-- 4. 查询总分前十名的成绩
select r.s_id,sum(r.r_score)
from result r
group by r.s_id
order by sum(r.r_score) desc
limit 10;

-- 5. 显示上面SQL的考生姓名
select r.s_id, s.s_name, sum(r.r_score) zf
from result r join student s on s.s_id = r.s_id
group by s.s_id
order by zf desc
limit 10;

-- 6. 显示上面SQL的考生所在学校和所属地区
select r.s_id, s.s_name, sum(r.r_score) zf, sc.sc_name, a.a_name from result r
join student s on s.s_id = r.s_id
join school sc on sc.sc_id = s.sc_id
join area a on a.a_id = sc.a_id
group by s.s_id
order by zf desc
limit 10;

增加难度:

-- 7. 统计一共有多少人参加高考,过一本线(大于等于550分),二本线(大于等于450分),专科线(大于等级250分的)分别有多少人;

-- 方案1:
-- 每个学生高考总分
select r.s_id,sum(r.r_score) zf from result r group by r.s_id order by zf desc;

-- 参加高考总人数 使用了distinct去重
select count(distinct s_id) from result;
-- 参加高考总人数 只要有分数就算参加了高考
select count(*) 参加高考总人数 from (select r.s_id,sum(r.r_score) from result r group by r.s_id) t;
-- 一本线
select count(*) 一本线人数 from (select r.s_id, sum(r.r_score) zf from result r group by r.s_id having zf >= 550 ) t;
-- 二本线
select count(*) 二本线人数 from (select r.s_id, sum(r.r_score) zf from result r group by r.s_id having zf >= 450 and zf < 550) t;
-- 专科线
select count(*) 三本线人数 from (select r.s_id, sum(r.r_score) zf from result r group by r.s_id having zf >= 250 and zf < 450) t;

-- 方案2:
-- 因为上表中高考总分被使用了很多次,因此可以将其作为一个临时表多次使用
-- 利用聚合函数不统计null值的原理 可以将不符合条件的直接设为null值
-- 语法:case when 条件 then 成立结果 else 不成立结果 end (优点类似三目运算符)
select count(*) 总人数,
count(case when t.zf >= 550 then 1 else null end) 一本线人数,
count(case when t.zf >= 450 and t.zf < 500 then 1 else null end) 二本线人数,
count(case when t.zf >= 250 and t.zf < 450 then 1 else null end) 专科人数
from (select r.s_id, sum(r.r_score) zf from result r group by r.s_id order by zf desc) t;

-- 方案3:
-- 利用sum函数也可以计算 不符合条件的设置为null值或者0值都可以
select sum(1) 总人数,
sum(case when t.zf >= 550 then 1 else 0 end) 一本人数,
sum(case when t.zf >= 450 and t.zf < 550 then 1 else 0 end) 二本人数,
sum(case when t.zf >= 250 and t.zf < 450 then 1 else 0 end) 专科人数
from (select r.s_id, sum(r.r_score) zf from result r group by r.s_id) t;

-- 8. 每个区参数考试人数
-- 方案1:多张表直接运算,最后去重 参与运算的数据比较多
select a.a_name, count(distinct r.s_id) 各区参考总人数 from result r
join student s on s.s_id = r.s_id
join school sc on sc.sc_id = s.sc_id
join area a on a.a_id = sc.a_id
group by a.a_id;

-- 方案2:在from后面进行去重并建立临时表,这样减少了很多数据参与运算
select a.a_name areaname,count(*) scount from student s 
inner join (select DISTINCT s_id sid from result) r on s.s_id = r.sid
inner join school sc on s.sc_id = sc.sc_id
inner join area a on a.a_id = sc.a_id
group by a.a_name;

-- 9. 每个区的录取情况
select a.a_name 区, count(*) 总人数,
count(case when t.zf >= 550 then 1 else null end) 一本线人数,
count(case when t.zf >= 450 and t.zf < 550 then 1 else null end) 二本线人数,
count(case when t.zf >= 250 and t.zf < 450 then 1 else null end) 专科线人数,
count(case when t.zf < 250 then 1 else null end) 未录取人数
from (select r.s_id s_id, sum(r.r_score) zf from result r group by r.s_id) t
join student s on s.s_id = t.s_id
join school sc on sc.sc_id = s.sc_id
join area a on a.a_id = sc.a_id
group by a.a_name;

知识点:case when 条件 then 成立结果 else 不成立结果 end
条件判断:可以用于判断一个条件然后得出一个值,最后返回给函数。类似于Java的三目运算符。

六、视图操作

视图是一个虚拟表,视图是不允许出现重复列的;封装视图的查询结果中也不能用用子查询。

语法:

  • 创建视图:create view 视图名 as
  • 删除视图:drop view [if exists] 视图名
  • 查看视图:select 字段1 [,字段N] from 视图名
  1. 将学生基本情况,所属学校,所属地区封装为一个视图
-- 如果存在该视图,则先删除(防止视图名冲突)
drop view if exists stu_v1;
-- 创建视图
create view stu_v1 as
select s.s_id id, s.s_name `name`, s.s_sex sex, s.s_birthday birthday, 
s.s_examnum examnum, sc.sc_name scname, a.a_name aname from student s
join school sc on sc.sc_id = s.sc_id
join area a on a.a_id = sc.a_id;
-- 查询视图
select * from stu_v1 limit 10;
  1. 将各分数线录取情况封装视图
-- sql语句
select count(s_id) totalnum,
sum(case when zf >= 550 then 1 else 0 end) firstnum,
sum(case when zf >= 450 and zf < 550 then 1 else 0 end) secondnum,
sum(case when zf >= 250 and zf < 450 then 1 else 0 end) thirdnum
from (select s_id, sum(r_score) zf from result group by s_id) t;

由于含有子查询,因此需要分两步操作

  1. 将每个学生的高考总分封装成一个视图

drop view if exists stu_v2;
create view stu_v2 as 
select s_id, sum(r_score) zf from result group by s_id;
  1. 根据高考总分查询录取情况
drop view if exists stu_v3;
create view stu_v3 as
select count(s_id) totalnum,
sum(case when zf >= 550 then 1 else 0 end) firstnum,
sum(case when zf >= 450 and zf < 550 then 1 else 0 end) secondnum,
sum(case when zf >= 250 and zf < 450 then 1 else 0 end) thirdnum
from stu_v2;

七、索引操作

索引是一种有效组合数据的方式,能够快速查找到指定记录。能够创建唯一索引,全文空间,空间索引等索引。
语法:

  • 创建索引:create [unique|fulltext|spatial] index 索引名 on 表名(列名1 [,列名N])
  • 删除索引:drop index 索引名 on 表名
  • 查询索引:show index from 表名

1.给学生表的学生姓名添加一个索引

create index index_student_sname on student(s_name);

2.查看学生表的索引

show index from student;
  • Table:创建索引的表
  • Non_unique:索引是否非唯一
  • Key_name:索引的名称
  • Column_name:定义索引的列字段
  • Seq_in_index:该列在索引中的位置
  • Null:该列是否能为空值
  • Index_type:索引类型

3.删除指定索引

drop index index_student_sname on student;

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