SQL练习

1. 创建表
	t_student(sno,sname,sex);	学生表
	t_course(cno,cname,credit);	课程表
	t_score(sno,cno,score);		成绩表

2. 录入数据
	insert into t_student values(1,'Mary','女');
	insert into t_student values(2,'Lucy','女');
	insert into t_student values(3,'Jack','男');
	insert into t_student values(4,'Tom','男');
	
	insert into t_course values
		(101,'数学',5),
		(102,'语文',4),
		(103,'英语',3);
	
	insert into t_score values(1,101,55);
	insert into t_score values(1,102,70);
	insert into t_score values(1,103,90);
	insert into t_score values(2,101,98);
	insert into t_score values(2,102,86);
	insert into t_score values(2,103,88);
	insert into t_score values(3,101,92);
	insert into t_score values(3,102,70);
	insert into t_score values(3,103,50);
	insert into t_score values(4,101,75);
	insert into t_score values(4,102,55);
	insert into t_score values(4,103,40);

==========================================================

问题1:
	显示完善的成绩信息,结果如下:
	
	+-------+--------+-------+
	| sname | cname  | score |
	+-------+--------+-------+
	| Mary  | 数学   |    55 |
	|...			 |
	| Tom   | 英语   |    40 |
	+-------+--------+-------+
	
----------------------------------------------------------------------------------------------
问题2:
	查询每门课的平均成绩并按从高到低排名,结果如下
	
	+--------+------------+
	| cname  | avg(score) |
	+--------+------------+
	| 数学   |    80.0000 |
	| 语文   |    70.2500 |
	| 英语   |    67.0000 |
	+--------+------------+

----------------------------------------------------------------------------------------------
问题3:
	查询学生 每门课成绩高于当前课程平均成绩的 成绩信息,结果如下:

	+-------+--------+-------+
	| sname | cname  | score |
	+-------+--------+-------+
	| Jack  | 数学   |    92 |
	| Lucy  | 数学   |    98 |
	| Lucy  | 语文   |    86 |
	| Lucy  | 英语   |    88 |
	| Mary  | 英语   |    90 |
	+-------+--------+-------+

----------------------------------------------------------------------------------------------
问题4:
	查询显示每个学生课程成绩的及格和不及格状态,结果如下:

	+-------+--------+-------+-----------+
	| sname | cname  | score | status    |
	+-------+--------+-------+-----------+
	| Jack  | 数学   |    92 | 及格      |
	| Jack  | 语文   |    70 | 及格      |
	| Jack  | 英语   |    50 | 不及格    |
	+-------+--------+-------+-----------+

----------------------------------------------------------------------------------------------
问题5:
	查询显示每门课及格和不及格人数,结果如下:

	+--------+--------+-----------+
	| cname  | 及格   | 不及格    |
	+--------+--------+-----------+
	| 数学   |      3 |         1 |
	| 语文   |      3 |         1 |
	| 英语   |      2 |         2 |
	+--------+--------+-----------+

----------------------------------------------------------------------------------------------
问题6:
	横向显示学生每门课的成绩,总成绩,平均成绩,结果如下

	+-------+--------+--------+--------+-----------+--------------+
	| sname | 数学   | 语文   | 英语   | 总成绩    | 平均成绩     |
	+-------+--------+--------+--------+-----------+--------------+
	| Jack  |     92 |     70 |     50 |       212 |      70.6667 |
	| Lucy  |     98 |     86 |     88 |       272 |      90.6667 |
	| Mary  |     55 |     70 |     90 |       215 |      71.6667 |
	| Tom   |     75 |     55 |     40 |       170 |      56.6667 |
	+-------+--------+--------+--------+-----------+--------------+

----------------------------------------------------------------------------------------------
问题7:
	查询显示学生每门课的成绩及名次,结果如下:

	+-------+--------+-------+---------+
	| sname | cname  | score | ranking |
	+-------+--------+-------+---------+
	| Lucy  | 数学   |    98 |       1 |
	| Lucy  | 语文   |    86 |       1 |
	| Mary  | 英语   |    90 |       1 |
	| Jack  | 数学   |    92 |       2 |
	| Lucy  | 英语   |    88 |       2 |
	| Jack  | 语文   |    70 |       3 |
	| Jack  | 英语   |    50 |       3 |
	| Mary  | 语文   |    70 |       3 |
	| Tom   | 数学   |    75 |       3 |
	| Mary  | 数学   |    55 |       4 |
	| Tom   | 语文   |    55 |       4 |
	| Tom   | 英语   |    40 |       4 |
	+-------+--------+-------+---------+
	
----------------------------------------------------------------------------------------------

* 数据库:
	* 数据存储仓库
	* 存放数据
		* io+file也可以实现数据永久存储(持久化)
	* 数据库可以通过编程实现数据库存取,比io+file存储方式更灵活,更方便,更安全,更有效。
* 数据库应用 (DBMS)* 数据库服务端 : 用来存放数据,提供对数据的各种操作功能(CRUD)
	* 数据库客户端 : 与服务端交互,提供数据操作的需求
			  通过sql命令向数据库服务端表达操作需求。
			  cmd窗口,workbench,jdbc
* sql命令:
	* DDL 数据定义语言
		* create database/table/user , alter , drop
	* DML 数据操作语言
		* insert , update , delete
	* DCL 数据控制语言
		* grant 赋予权限
	* DQL 数据查询语言
		* select
	* TCL / TPL 事务控制语言
		* commit , rollback
		* 事务四种特性:
			* 原子性,隔离性,一致性,持久性
* 常见sql操作:
	* 建表
	* CRUD (增删改查)
	* 过滤,排序,分页,子查询,关联查询,分组
* sql应用:
	1. cmd登录数据
	2. 创建database 数据库区域
	3. 选择数据库区域
	4. 建表
	5. 录入数据
	6. 查询测试

* 问题1* 要查询显示成绩
	* 就必须查询成绩表
	* 因为需要显示完善的数据(显示具体的学生名字和课程名字)
	* 成绩表中没有这些内容
	* 就需要从其他表中查询
	* 就需要关联查询。
		* 是否需要关联查询
		* 只需要看所需的数据来自于那些表。
	* 语句:
		select
			sname,
			cname,
			score
		from 
			t_score join t_student on t_score.sno=t_student.sno
				join t_course on t_score.cno=t_course.cno
	
	* 注意:
		* 两个表数据的连接
		* 默认效果是A表的每条记录与B表每条记录横向组成一条新纪录。
		A			B
		1  2  3			1 3 5
		4  5  6			4 6 8
		
		A join B
		1  2  3  1  3  5
		1  2  3  4  6  8
		4  5  6  1  3  5
		4  5  6  4  6  8

		记录数:笛卡尔积
	* 注意:
		两个表数据关联后
		还需要根据逻辑
			* 可以是根据业务分析的
			* 可以是人为规定。
			* 两个表的数据关系就像娱乐圈的绯闻一样。你说有就有,你说没有就没有。
		将没有关系的数据(不应该组成一行的数据)过滤掉
	* 注意:
		* 连接有两种
			* inner join 内连接
				* 只将有关联的数据连接
			* outer join 外连接
				* 有关联的数据连接
				* 关联数据以外的数据也需要。
				* 左外  left outer join
				* 右外  right outer join
* 问题2* 每一个,各个这样的字眼,马上想到分组。
	* 因为是每门课,所以按照课程分组(课程名字,课程编号)
	* 无论按照谁分组,最终显示时需要显示具体的课程名字
	* 课程名与分数在不同的表中,需要关联查询。
		* 通过分析发现,很多问题中都需要关联
		* 所以可以使用视图。
			* 视图可以理解成一个查询语句的封装
			* 将一个经常使用,又比较复杂的查询语句可以封装成一个视图
			* 语法如下:
				create view v_score as 
					select
						sname,
						cname,
						score
					from 
						t_score join t_student on t_score.sno=t_student.sno
							join t_course on t_score.cno=t_course.cno

				select * from v_score ;
	* sql编码:
		select cname,avg(score) from v_score group by cname order by avg(score)  desc ;
* 问题3* 需要使用每个学生成绩与其对应的平均成绩比较。
	* 哪来的平均成绩?
		需要先计算平均成绩(问题2结果)
	* 最终需要普通成绩与平均成绩比较
		普通成绩在v_score
		平均成绩在问题2查询的结果中
			查询结果也可以当成一张表(虚拟表,临时表)
	* 所以需要2个结果关联。
		select
			sname,
			v_score.cname,
			score,
			avgscore
		from 
			v_score join (select cname,avg(score) as avgscore from v_score group by cname order by avg(score)  desc ) as t
			             on v_score.cname = t.cname
		where 
			v_score.score >= t.avgscore;
* 问题4* 显示时内容至少需要来自3张表
	* 显示时除了可知的sname,cname,score以外
	* 还需要多显示一个分数状态
	* 根据逻辑分析,这个分数状态需要根据分数,进行判断获得。
		* if() : 兼容问题
		* case-when-end
	select 
		sname,
		cname,
		score,
		if(score>=60,'及格','不及格') status
	from
		t_score sc inner join t_student st on sc.sno = st.sno
			   inner join t_course c  on sc.cno = c.cno ;
* 问题5* 需要在问题4的基础上实现行列转换
		* 可以将问题4的sql包装成视图。
		create view v_score2 as select4
	* 在行列转换时,需要汇总结果,就需要分组,因为要每门课的信息
		select
			cname,
			sum( if(status='及格',1,0) ) 及格,
			sum( if(status='及格',0,1) ) 不及格
		from
			v_score2
		group by cname
	---------------------------------------
	* 基于问题4的查询结果
	* 首先进行分组
	* 分组后,脑补分组效果
		* 将某一个组中不及格数据过滤掉,剩余的数据count汇总
			select count(status) from v_score2 where status='及格'and cname = '数学';
		* 上述语句中,可以对某一门课及格记录count汇总
		* 但问题是,在整个查询显示过程中,怎么知道是哪一门课
			* 回顾:select查询的内部处理
				* 数据库表中有n条记录
				* 使用select查询时
				* 不是一下子查出来
				* 是一条一条查出来的
				* 查出一条,按照where过滤,符合条件保留,否则去掉。
			* 查询显示时,可以用当前这条记录的某一个字段为条件,配合子查询。
			select 
				cname,
				(select count(status) from v_score2 vi where status='及格' and vi.cname=vo.cname) 及格,
				(select count(status) from v_score2 vi where status='不及格' and vi.cname=vo.cname) 不及格
			from
				v_score2 vo
			group by cname
* 问题6:
	自行解决
* 问题7* 先实现3张表的关联
	* 在sname,cname,score3个显示字段的基础上增加一个名次显示字段
	* 如何获得名次呢?
		* 基于select查询特点
		* 每查询获得一条记录,就可以想办法获得他的名次
		* 只需要以一条记录特点为类,算出名次。就可以获得所有名次了。
		* 假设某一个学生的成绩信息是
			Lucy 数学 98
		* 如何获得名次呢
			* 通过比较获得比Lucy数学分数高的其他同学的数学成绩
			* 比lucy数学成绩高的同学有几个,lucy就是+1那个名次。
			select count(*)+1 from v_score where sname != 'lucy' and cname='数学' and score > 98
select
	sname,
	cname,
	score,
	(
		select 
		  count(*)+1 
		from (
			select sname,cname,score
			from t_score sc1 inner join t_student st1 on sc1.sno=st1.sno
					 inner join t_course c1 on sc1.cno=c1.cno

		) t
		where 
		  t.sname != st.sname and t.cname=c.cname and t.score > sc.score
	) 名次
from
	t_score sc inner join t_student st on sc.sno = st.sno
		   inner join t_course c on sc.cno = c.cno
order by cname , 名次 asc ;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值