欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享,与更多的人进行学习交流
本文收录于SQL应知应会专栏,本专栏主要用于记录对于数据库的一些学习,有基础也有进阶,有MySQL也有Oracle
create table table_grade(
id int,
user_name varchar(20),
course varchar(10),
score decimal(5,2)
);
insert into table_grade(id,user_name,course,score) values (1,'张龙','语文','78'),(2,'张龙','数学','95'),(3,'张龙','英语','81');
insert into table_grade values(4,'赵虎','语文','97'),(5,'赵虎','数学','78'),(6,'赵虎','英语','91');
insert into table_grade set id = 7,user_name = '王五',course = '语文',score = '81';
insert into table_grade set id = 8,user_name = '王五',course = '数学',score = '55';
insert into table_grade set id = 9,user_name = '王五',course = '英语',score = '75';
insert into table_grade values(10,'马六','语文','87'),(11,'马六','数学','65'),(12,'马六','英语','75');
alter table table_grade modify score decimal; -- decimal默认10位整数
现实中用到的一些数据是明细数据/流水账
用户名 商品 购买时间
A 手机 4.20
A U盘 4.21
B …
B …
update table_grade set id = 4 where user_name = '马六'
alter table table_grade add oid varchar(10)
alter table table_grade modify oid varchar(50)
update table_grade set oid = uuid(); -- 设置一个代理键
alter table table_grade rename column id to user_id -- 修改某列名字
alter table table_grade modify oid varchar(50) first -- 修改某列位置
show columns from table_grade; -- 查看表各列
show keys from table_grade; -- 查看索引
通过聚合将多用户变成单用户,使用哪一个聚合函数与数据有关
使用max()则选取最大的一条
- 现在的表如下所示
张龙 语文 78
张龙 数学 95
张龙 英语 81- 我们想显示成:
语文 数学 英语
张龙 78 95 81- 这样的话,张龙语文只能有一个成绩,若有多个成绩
- ** 思路1:用列表把多个成绩放在一起 **
语文 数学 英语
张龙 78,88 95 81- ** 思路2:取一个最近的考试成绩(这就需要在表中加一个时间列)**
- ** 思路3:如果两次成绩重复了,比如都是100,就可以用max或min**
语文 数学 英语
张龙 100 95 81
- 如果用sum的话,统计结果就变成了200
语文 数学 英语
张龙 200 95 81
- 增加一个时间限制
alter table table_grade add column exam_date date after score;
update table_grade set exam_date = date_format(from_unixtime( -- from_unixtime() 将时间戳转换为日期,date_format()设置一下日期格式
unix_timestamp('2023-01-01') -- 将日期转为一个时间戳,此处是用1月1号加随机的天数(由于天数是1月1到4月28,所以最终的结果不会超过4月28)
+ floor( rand() * -- rand() 随机数[0,1),floor() 向下取整
(unix_timestamp('2023-04-28') - unix_timestamp('2023-01-01') + 1) -- 4月28减去1月1号的天数,因为rand的范围是[0,1),所以后面+1是为了保证可以取得4月28
)
),'%Y-%m-%d');
前提: 假设张龙各科只考了一次,对此进行行转列
- 为了可以看出差异性,删除王五的英语,马六的语文
delete from table_grade where user_name = '王五' and course = '英语'; delete from table_grade where user_name = '马六' and course = '语文';
select user_id '学生ID',
max(case when course = '语文' then score else null end) '语文', -- 因为只有一个成绩,max min 没区别; else null 可以省略,默认其他情况就是null
max(case when course = '数学' then score end) '数学',
max(case when course = '英语' then score end) '英语'
from table_grade
group by user_id -- 用了聚合函数,那就用group by 去显示
select user_id '学生ID',
(select max(user_name) from table_grade where user_id = t.user_id) user_name, -- 使用相关子查询(关联子查询)
max(case when course = '语文' then score end) '语文',
max(case when course = '数学' then score end) '数学',
max(case when course = '英语' then score end) '英语'
from table_grade t
group by user_id;
Subquery returns more than 1 row
,即子查询返回了多行。所以此处需要加一个函数进行处理,至于决定加哪一个函数,根据需求决定,这后面讲