Bootstrap

10.30总结

10.30总结

查询结果为一张表,需要as 一个变量名

作业回顾1:MySQL基本操作作业

如果创建表后,在输入数据,也就是Inter into 这一环节,由于表的字段和输入数据的字段对应不上,导致数据无法输入进去,那么,需要删除这个表,再进行修改表的字段,而后输入数据才行;不删表,继续运行create这一环节,那么新字段不会加进去,依旧错误。
### 资料
create database if not exists homework charset utf8mb4;

-- 创建员工表
create table if not exists employee(
    eno int primary key comment '员工编号',
    ename varchar(30) not null comment '员工姓名',
    eage int not null comment '年龄',
    esex char(5),check ( esex='男' or esex='女' ),
    ejob varchar(20) comment '职位',
    ehiredate date comment '员工入职时间',
    ebonus float comment '员工奖金',
    ebsalary float comment '员工底薪',
    deptno int comment '部门编号'
);
select * from employee;
drop table employee;  -- 如果表字段和数据字段对不上,那么先删除表,再改字段,然后运行才行,不删不行
insert into employee(eno, ename, eage, esex, ejob, ehiredate, ebonus, ebsalary, deptno) values
(1,'李鹏飞',32,'男','经理','2016-11-12',5000,8000,10),
(2,'王鹏飞',27,'男','销售员','2018-10-20',2000,1000,10),
(3,'肖美',24,'女','前台','2019-03-21',0,3500,20),
(4,'王乐乐',30,'女','经理','2017-03-02',0,9000,20),
(5,'张丽丽',28,'女','行政人员','2019-11-11',0,5000,20),
(6,'徐华',33,'女','销售员','2019-11-17',500,4000,10),
(7,'赵辉',40,'男','经理','2016-11-17',0,50000,30),
(8,'王伟',35,'男','开发工程师','2018-11-28',0,30000,30),
(9,'钱慧慧',28,'女','开发工程师','2019-04-17',0,25000,30),
(10,'孙雯彩',29,'女','开发工程师','2017-09-15',0,20000,30);
drop database if exists homework;   # 删除数据库
drop table if exists employee;      # 删除数据表操作
-- 3.修改肖美的奖金为500
-- 如果在workbench  中 修改 安全等级  set sql_safe_updates = 0;   1 安全等级高  0 安全等级低

update employee set ebonus = 500 where ename = '肖美';
select * from employee;
-- 4.删除名为孙雯彩的员工
delete from employee where ename = '孙雯彩';
-- delete   删除表中的数据  如果没有where 条件  认为不安全的删除
-- 如果是delete删除数据  添加数据 直接 insert into
-- delete  数据操作语言    同类的  update   insert into

-- drop     删除表中的数据和表结构   删除表结构  -- 数据自然就没有了
-- 如果是drop删除 添加数据  得先有表  create table  --- insert  into
-- 数据定义语言   create  alter

注意:employee.ebsalary:

-- 7.找出奖金高于底资的员工
-- ebonus  ebsalary 筛选查询

select * from employee where ebonus>employee.ebsalary;
-- 9.找出部门编号为20中的经理,和部门编号为10中所有销售员的详细资料
-- 20 and  经理   10  and 销售员
select  * from employee where (deptno=20 and ejob='经理') or (deptno=10 and ejob='销售员');

注意:分组查询

-- 10.查询每个部门,男女各自的人数【不写】   分组查询
/*
    部门编号   性别  人数
    10102020*/

select deptno,esex,count(eno) as '人数'
    from employee
    group by deptno,esex;

注意:两种去重办法:distinct 和分组去重

-- 11.查询有奖金的员工的职位
-- 去重  distinct
select distinct ejob from employee where ebonus>0;
-- 去重 分组去重
select ejob from employee where ebonus>0 group by ejob;

注意:模糊去重

-- 12.查询名字由三个字组成的员工
-- 模糊 ___
select * from employee where ename like '___';

注意: 三种查询办法:

# 13.查询2017年入职的员工信息
-- like
select * from employee where ehiredate like '2017%';

-- left
select * from employee where left(ehiredate,4) = 2017;

-- year()
select * from employee where year(ehiredate) = 2017;

注意: 工资相加

-- 14.每个部门的平均薪资【不写】 分组
-- 分组字段
/*
    部门  平均薪资
    10     100
    20     200
 */
select deptno,avg(ebonus+ebsalary) as '平均工资'
    from employee
    group by deptno;

注意:薪资高于一个数问题:

-- 15.最高薪资高于15000的部门编号【不写】
-- 1. 每个部门的最高薪资
-- 分组  部门编号
select deptno,max(ebonus+ebsalary) from employee group by deptno;

-- 2. 高于15000的  分组后的筛选  筛选的内容是 最大值要满足xxx要求  聚合函数
select deptno from employee group by deptno having max(ebonus+ebsalary)>15000;

作业回顾2:数据库练习综合题

# 创建学生表  学号  姓名  生日  性别
create table student(
sid varchar(10) primary key,
sname varchar(20) not null,
sbirthday date not null,
ssex char(3) not null default '男'
);

# 添加数据
insert into student values('01' , '赵雷' , '1990-01-01' , '男');
insert into student values('02' , '钱电' , '1990-12-21' , '男');
insert into student values('03' , '孙风' , '1990-05-20' , '男');
insert into student values('04' , '李云' , '1990-08-06' , '男');
insert into student values('05' , '周梅' , '1991-12-01' , '女');
insert into student values('06' , '吴兰' , '1992-03-01' , '女');
insert into student values('07' , '郑竹' , '1989-07-01' , '女');
insert into student values('08' , '王菊' , '1990-01-20' , '女');

# 教师表 编号 姓名
create table teacher(
tid varchar(10) primary key,
tname VARCHAR(20) not null
);

# 添加数据
insert into teacher values('01' , '张三');
insert into teacher values('02' , '李四');
insert into teacher values('03' , '王五');

# 课程表 编号 课程名  代课老师编号
create table course(
cid varchar(10),
cname VARCHAR(20) not null,
tid varchar(10) not null,
PRIMARY KEY(cid)
);

# 添加数据
insert into course values('01' , '语文' , '02');
insert into course values('02' , '数学' , '01');
insert into course values('03' , '英语' , '03');

# 成绩表 学生编号 课程编号 成绩
create table score(
sid varchar(10) ,
cid varchar(10) ,
score FLOAT(4,2)
);

# 添加数据
insert into score values('01' ,'01' , 80);
insert into score values('01' ,'02' , 90);
insert into score values('01' ,'03' , 99);
insert into score values('02' ,'01' , 70);
insert into score values('02' ,'02' , 60);
insert into score values('02' ,'03' , 80);
insert into score values('03' ,'01' , 80);
insert into score values('03' ,'02' , 80);
insert into score values('03' ,'03' , 80);
insert into score values('04' ,'01' , 50);
insert into score values('04' ,'02' , 30);
insert into score values('04' ,'03' , 20);
insert into score values('05' ,'01' , 76);
insert into score values('05' ,'02' , 87);
insert into score values('06' ,'01' , 31);
insert into score values('06' ,'03' , 34);
insert into score values('07' ,'02' , 89);
insert into score values('07' ,'03' , 98);

select * from student;
select * from score;
select * from teacher;
select * from course;

注意:as命名:

# 1.查询姓“张”的老师的个数
select count(*) as '个数' from teacher where tname like '张%';

注意:02不是2

-- 2.查询课程编号为“02”的总成绩
-- 成绩  score
select sum(score) as '总成绩' from score where cid = '02';

# 补充:
-- 查询每个课程的总成绩
-- 查询每个课程的总成绩
-- 分组  字段  课程
/*
    课程  成绩
    01
    02
    03
 */
select cid,sum(score)
    from score
    group by cid;

注意:like和正则

-- 3、查询名字中含有“风”字的学生信息
-- student
select * from student where sname like '%风%';
select * from student where sname regexp '风';

注意:取year

-- 4、1990年出生的学生名单
select * from student where year(sbirthday) = 1990;

注意:distinct去重

-- 5、查询选了课程的学生人数
-- score
select count(distinct sid) from score;

注意:排序问题

-- 9、查询每门课程的平均成绩,结果按平均成绩升序排序,平均成绩相同时,按课程号降序排列
-- 排序  order by  排序字段  asc desc
-- 分组  课程
-- 首先按照第一个字段的排序规则进行排序  如果第一个字段的值是一样的  再按照第二个字段的排序规则进行排序
select cid,avg(score) from score group by cid order by avg(score) asc,cid desc;

注意:分组

-- 10、查询同名同性学生名单并统计同名人数
-- 名字相同  性别相同
-- 根据 名字 性别  两个字段 分组
select sname,ssex,count(sid)
    from student
    group by sname,ssex
    having count(sid)>=2;

注意:大于

-- 11、查询平均成绩大于60分的学生的学号和平均成绩
-- 成绩表
select sid,avg(score)
    from score
    group by sid
    having avg(score)>60;

总结:

连接查询:

1.笛卡尔积

空的也算行乘进去了

产生 
select * from A,B
一次性查询多张表  将A表中的每一条数据和B表中的每一条数据进行连接,
产生的结果的数据量为 A表中数据条数*B表中的数据条数
A中的有10条数据  B中有5条数据  连接形成的结果中  10*5=50条数据 

笛卡儿积的产生是要避免的  
表和表之间是有关系的,进行表连接的时候要指定连接条件 

1.模式举例:

select * from tb_student;
select * from tb_score;
select * from tb_course;
select * from tb_class;
-- 笛卡尔积   查询的时候 要避免 笛卡尔积的出现
-- 一次查询两种表  10个学生  4个班级  每个学生都和所有的班级进行一次连接  10*4=40
select * from tb_student,tb_class;

# 解决办法:让二者相等就行:
-- 想要的数据   学生在班级 班级的名字是什么??
-- 10个学生 每个学生都有所在的班级  班级都有一个确定的名字
-- 避免笛卡儿积  进行表连接的时候  给定连接条件 (分析表和表之间的关系)
-- 学生表和班级表  关系 -- 班级编号
-- 成绩表和学生表  关系 -- 学生的编号
-- 成绩表和课程表  关系 -- 课程编号
-- 上述代码下 加连接条件
select stu_name,class_name from tb_student,tb_class
         where tb_student.class_no = tb_class.class_no;

2.内连接查询

两张表同时满足条件 空的是连不上的,直接排除了

写法1 
	select 字段  from 表1,表2 where 连接条件 and 筛选条件
	group by 分组字段  having 分组后的筛选  order by 排序字段 排序规则
	
写法2 
	select 字段  from  表1 join 表2  on 连接条件
	where 筛选条件  group by 分组字段  having 分组后的筛选  order by 排序字段 排序规则
	
写法3
	select 字段  from  表1 inner join 表2  on 连接条件  inner join 表3 on 连接条件 
	where 筛选条件  group by 分组字段  having 分组后的筛选  order by 排序字段 排序规则
	
执行顺序
	from --  join  -- where --  group by -- having -- select -- order by 

增加数据,内连接举例:

inner可以省略

-- 数据的修改
-- 增加一个班级
select * from tb_class;
insert into tb_class value (5,'网安');
-- 学生表中增加一个学生
select * from tb_student;
insert into tb_student value (11,'哈哈','1999-10-10','女',null);


select * from tb_class;
select * from tb_student;
-- 内连接  左右两种表都满足连接条件
select *
    from tb_student
    inner join tb_class
    on tb_student.class_no = tb_class.class_no;
  1. 例子
-- 查询学了围棋的学生的编号、学生姓名和所在班级
-- 表和表之间的关系
-- 围棋 --> 课程表   课程编号 课程名字
-- 课程编号 和 成绩表 能关系   成绩表中 (学生编号 课程编号 成绩)
-- 学生表
-- 用到的表  课程表  成绩表  学生表
-- stu_no 学生表  成绩表中也有  重复的
select tb_student.stu_no,stu_name,class_no
    from tb_student
    inner join tb_score
    on tb_student.stu_no = tb_score.stu_no
    inner join tb_course
    on tb_score.course_no = tb_course.course_no
    where course_name = '围棋';
  1. 例题:distinct 去重,名字不能统计两次
-- 查询学了围棋或者手游的学生姓名
-- 学生表   课程表   成绩表
select distinct stu_name
    from tb_student
    inner join tb_score
    on tb_student.stu_no = tb_score.stu_no
    inner join tb_course
    on tb_score.course_no = tb_course.course_no
    where course_name in ('围棋','手游');

3.外连接 - 左外连接

左表中数据都要,右表中找满足条件的数据

左表全都要,右表能连上的连,连不上的用null填充

select 字段  from  表1 left join 表2  on 连接条件
	where 筛选条件  group by 分组字段  having 分组后的筛选  order by 排序字段 排序规则

1.模式举例:

-- 左外连接  左表中的数据都要  右边找满足条件
-- tb_student 作为左表  -- 左表中的数据都要  11个学生 结果中 11个学生
-- 哈哈 没有班级 连接条件不满足 右表中补充null
select *
    from tb_student
    left join tb_class
    on tb_student.class_no = tb_class.class_no;

2.例题:

-- 获取所有每个的学生 的总成绩
-- 展示  学生编号 学生姓名 总成绩
--       1        哈哈   sum()
-- 学生姓名  学生表   字段  学生编号
-- 成绩     成绩表
-- 如果学生没有选课  总成绩 0
-- ifnull(字段名,替换的值)   如果字段为空  替换成指定的值
-- 左连接  ifnull()
select tb_student.stu_no,stu_name,sum(ifnull(score,0))
    from tb_student
    left join  tb_score
    on tb_student.stu_no = tb_score.stu_no
    group by tb_student.stu_no;
select * from tb_student;

3.例题

左连接中 from后面跟着谁,谁就在最左边

-- 查询每个班级的学生人数 班级编号 班级名称  人数
-- 班级表  班级编号 班级名称
-- 人数   计数  学生  学生表 -- 班级编号
select tb_class.class_no,class_name,count(stu_no)
    from tb_class
    left join tb_student
    on tb_class.class_no = tb_student.class_no
    group by tb_class.class_no;

4.例题

平均成绩 和 起别名 as

1.-- 查看每个课程的平均成绩  展示信息 课程号  课程名称  平均成绩
-- 课程名称  课程表
-- 成绩   成绩表   连接字段  课程编号
select tb_course.course_no,course_name,avg(score) as '平均成绩'
    from tb_course
    left join tb_score
    on tb_course.course_no = tb_score.course_no
    group by tb_course.course_no;

2.-- 查看每个班级的总成绩  展示信息 班级编号  班级名称  总成绩
-- 班级名称  班级表  (班级编号 编辑名称 )
-- 总成绩    成绩表    (学生编号 课程编号  成绩)
-- 中间表    学生表    (学生编号  班级编号)
select tb_class.class_no,class_name,ifnull(sum(score),0)
    from tb_class
    left join tb_student
    on tb_class.class_no = tb_student.class_no
    left join tb_score
    on tb_student.stu_no = tb_score.stu_no
    group by tb_class.class_no;
  1. 例子(重点)
-- 查看学生总成绩低于其所在班级平均成绩的学生的学号 姓名 总成绩 班级平均成绩
/*
    学生编号  学生姓名   总成绩   学生班级  班级平均分
    1                      100   1      80
    2                      200   2      120
*/
-- 1. 每个学生的总成绩   分组字段 学生
-- 学生表  成绩表  连接字段 学生编号
select tb_student.stu_no,tb_student.class_no,ifnull(sum(score),0) as '总成绩'
    from tb_student
    left join tb_score
    on tb_student.stu_no = tb_score.stu_no
    group by tb_student.stu_no;

-- 2. 每个班级的平均成绩   分组字段  班级  (严格  班级表 所有的班级)
-- 班级编号  平均成绩
-- 班级表  班级编号 班级名称
-- 学生表(所在班级 - 有的班级没有学生)
-- 成绩表 (学生编号 课程编号 成绩)
-- 班级平均分   班级的总分 / 去重之后的人数
-- 3班   66+93+80 = 239    班级中的人数 2个  班级的平均分   239/2=119.5
-- 79.66666666666667  239/3 = 79.66666667
select tb_class.class_no,ifnull(sum(score) / count(distinct tb_student.stu_no),0) as '班级的平均分'
    from tb_class
    left join tb_student
    on tb_class.class_no = tb_student.class_no
    left join tb_score
    on tb_student.stu_no = tb_score.stu_no
    group by tb_class.class_no;

-- 上述联系
-- 学号 姓名 总成绩 班级平均成绩
with
t as (select tb_student.stu_no,tb_student.stu_name,tb_student.class_no,ifnull(sum(score),0) as '总成绩'
    from tb_student
    left join tb_score
    on tb_student.stu_no = tb_score.stu_no
    group by tb_student.stu_no),
t1 as (select tb_class.class_no,tb_class.class_name,ifnull(sum(score) / count(distinct tb_student.stu_no),0) as '班级的平均分'
    from tb_class
    left join tb_student
    on tb_class.class_no = tb_student.class_no
    left join tb_score
    on tb_student.stu_no = tb_score.stu_no
    group by tb_class.class_no)
select t.stu_no,t.stu_name,t.总成绩,t1.班级的平均分 from t inner join t1 on t.class_no = t1.class_no
    where t.总成绩 > t1.班级的平均分;

4.外连接 - 右外连接

右表中数据都要,左表找满足条件的数据

select 字段  from  表1 right join 表2  on 连接条件
	where 筛选条件  group by 分组字段  having 分组后的筛选  order by 排序字段 排序规则

举例:

-- 右连接  右表中的数据都要 左表中找满足条件的
-- tb_class 表中的数据都要 5班  没有学生属于5班  没有学生能和这条数据连接
-- tb_student补充null
select *
    from tb_student
    right join tb_class
    on tb_student.class_no = tb_class.class_no;
    
-- 右外 可以变成左外 from那里换一下就行
select *
    from tb_class
    left join  tb_student
    on tb_student.class_no = tb_class.class_no;

5.全外连接

左右两表中的数据都要 能满足连接条件的进行连接 不能满足的 没有的一方补充null

full join 但是mysql不支持  

mysql 中想要展示两表中的全部数据, 需要 左连接 + 右连接 + union

union 的作用 纵向合并结果集  也就是上下合并  去重后的结果 

union all 的作用 纵向合并结果集  未去重的结果 

在合并的时候要求 字段一致

# 错误演示:

学生编号 学生姓名  


课程编号  课程名字

例子:

tb_class.* 展示班级表里的所有

select 后的字段要求一致

# 用union解决:

-- 所有学生的班级情况
-- 所有班级的情况
-- 展示所有学生 学生班级    所有的学生体现    所有的班级体现
# --体现所有学生可以用学生做连接  体现所有的班级可以用班级做连接
select tb_student.stu_no,tb_student.stu_name,tb_student.gender,tb_class.*
    from tb_student
    left join tb_class
    on tb_student.class_no = tb_class.class_no   # 这里没分号,分号意味着结束语句
union
#  体现所有的班级可以用班级做连接
select tb_student.stu_no,tb_student.stu_name,tb_student.gender,tb_class.*
    from tb_student
    right join tb_class
    on tb_student.class_no = tb_class.class_no;


# 用union all解决:

-- 去重
with t as
(select tb_student.stu_no,tb_student.stu_name,tb_student.gender,tb_class.*
    from tb_student
    left join tb_class
    on tb_student.class_no = tb_class.class_no
union all
select tb_student.stu_no,tb_student.stu_name,tb_student.gender,tb_class.*
    from tb_student
    right join tb_class
    on tb_student.class_no = tb_class.class_no)

select distinct * from t;   # 直接去重


# 也可以这样去重:

select distinct * from
        (select tb_student.stu_no,tb_student.stu_name,tb_student.gender,tb_class.*
            from tb_student
            left join tb_class
            on tb_student.class_no = tb_class.class_no
        union all
        select tb_student.stu_no,tb_student.stu_name,tb_student.gender,tb_class.*
            from tb_student
            right join tb_class
            on tb_student.class_no = tb_class.class_no) as t;
                                              # 当查询结果作为一张表,要as一个变量名

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

自连接

自己连接自己 

表关系来源于同一张表 把一张表视作两张或者多张 达到查询的需要 

例子:

-- 自连接查询
-- 查询 1号课程比2号课程成绩高的学生
-- 1. 1号课程的成绩  score
select * from tb_score where course_no = 1;
-- 2. 2号课程的成绩
select * from tb_score where course_no = 2;

# 内连接:
with
t as (select * from tb_score where course_no = 1),
t1 as (select * from tb_score where course_no = 2)
select t.stu_no from t inner join t1 on t.stu_no = t1.stu_no and t.score>t1.score;

-- 自连接
select t.stu_no
    from tb_score as t         -- 视作1号课程的数据表
    inner join tb_score as t1  -- 视作为2课课程的数据
    on t.course_no = 1
    and t1.course_no = 2
    and t.stu_no = t1.stu_no
    and t.score>t1.score;

排序查询

默认是升序排

书写顺序

select distinct 字符 from 表1  inner join 表2 on 连接条件 where 筛选条件  group by 分组字段
having 分组后的筛选 order by 排序字段1 排序方式,排序字段2 排序方式 

排序方式不指定 默认是升序排序  asc
降序   desc 

执行顺序 
from --  join  -- where -- group by  -- having -- select -- distinct -- order by  

例子:

-- 获取每个学生的总成绩  按照总成绩降序排序
-- 1. 获取每个学生的总成绩  student left join score
-- 如果成绩相同 按照学生编号降序排序
-- 按照第一个排序字段进行指定形式的排序 如果第一个字段相同 再按照第二个字段进行指定形式的排序
select tb_student.stu_no,ifnull(sum(score),0) as '总成绩'
    from tb_student
    left join tb_score
    on tb_student.stu_no = tb_score.stu_no
    group by tb_student.stu_no
    order by 总成绩 desc,tb_student.stu_no desc ;

分页查询

limit  

书写顺序

select distinct 字符 from 表1  inner join 表2 on 连接条件 where 筛选条件  group by 分组字段
having 分组后的筛选 order by 排序字段1 排序方式,排序字段2 排序方式 limit 数字
-- 取前xxx条  
select distinct 字符 from 表1  inner join 表2 on 连接条件 where 筛选条件  group by 分组字段
having 分组后的筛选 order by 排序字段1 排序方式,排序字段2 排序方式 limit m offset n
-- 偏移n条取m条
-- 前n条不取 从第n+1条开始  取m条 

执行顺序
from --  join  -- where -- group by  -- having -- select -- distinct -- order by -- limit
  1. 例子:
-- 分页查询   
select * from tb_student limit 5;  # 只看前5条

-- 查看第6条到第10条
-- 跳过前5条 取5条数据
select * from tb_student limit 5 offset 5;

-- 简化 limit m,n
-- 跳过m 条 取 n条
select * from tb_student limit 5,3;
  1. 例子:理解groupby 和 partition by

数据:

/*
学生编号  学生姓名  所在班级
1        小红      1
2        小兰       2
3       小明         3
4        小兵        1
5         乐乐        2
6        小华         3
如果是根据班级 group by  分组
结果中就是3条数据  影响数据的总行数

partiton by  不会影响数据的总行数
只是把相同班级的数据放在一起
学生编号  学生姓名  所在班级
1        小红      1
4        小兵       1
2        小兰       2
5         乐乐      2
3       小明        3
6        小华       3
*/

create table if not exists ym_sales(
    yearly int comment '年份',
    monthly int comment '月份',
    sales int comment '销量',
  primary key(yearly, monthly)
);
insert into ym_sales values
(2021, 1, 84),
(2021, 2, 24),
(2021, 3, 50),
(2021, 4, 73),
(2021, 5, 65),
(2021, 6, 91),
(2021, 7, 52),
(2021, 8, 85),
(2021, 9, 57),
(2021, 10, 32),
(2021, 11, 64),
(2021, 12, 69),
(2022, 1, 82),
(2022, 2, 13),
(2022, 3, 52),
(2022, 4, 55),
(2022, 5, 87),
(2022, 6, 32),
(2022, 7, 46),
(2022, 8, 81),
(2022, 9, 14),
(2022, 10, 68),
(2022, 11, 51),
(2022, 12, 56);

create table if not exists yp_sales(
    yearly int comment '年份',
    product varchar(10) comment '产品',
    sales int comment '销量',
  primary key(yearly, product)
);
insert into yp_sales values
(2021, 'A', 82),
(2021, 'B', 13),
(2021, 'C', 55),
(2021, 'D', 55),
(2021, 'E', 87),
(2021, 'F', 32),
(2021, 'G', 46),
(2022, 'A', 84),
(2022, 'B', 24),
(2022, 'C', 50),
(2022, 'D', 73),
(2022, 'E', 65),
(2022, 'F', 91),
(2022, 'G', 52);

操作:

年份和月份的销售表   年份和产品的销售表
-- ym-sale          yp-sale
select * from ym_sales;
select * from yp_sales;

group by:

-- group by   分组 分组影响数据的函数
-- 获取 每年的销量和
-- 分组字段 年份  2021 2022两个年份 最终的数据行数 2行
select yearly,sum(sales) from ym_sales group by yearly;

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

partition by :

-- partition by  不影响数据的总行数
-- over 中指定的分组 将每一个分组视作一个窗口
select yearly,sum(sales) over (partition by yearly)
    from ym_sales;

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

over中不指定分组: 这个1383是 (2021年)的637 + (2022年)的736

-- over中如果不指定分组  将所有的数据视作一个窗口
select yearly,sum(sales) over ()
    from ym_sales;

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

as t 把它变成一张表

-- 获取每年的平均销量 ym_sales 不影响数据行数  表中 增加一列 作为平均销量
-- where 中的列 要是表中的字段
with t as
(select *,avg(sales) over (partition by yearly) as '年平均销量'
    from ym_sales)
select * from t where t.sales>t.年平均销量;

-- 如果不用窗口函数 怎么办??
-- 1.获取每年的平均销量     2021 68  2022 53
with t as
(select yearly,avg(sales) as '年平均销量'
    from ym_sales
    group by yearly)
select ym_sales.*,t.年平均销量
    from ym_sales
    inner join t
    on ym_sales.yearly = t.yearly
    where ym_sales.sales>t.年平均销量;

窗口指定

-- 求每年的累计销量
-- 子窗口
/*
2021 1 84
2021 2 84+24
2021 3 84+24+50
2021 4 84+24+50+73
2021 12

2022 1 82
2022 2 82+13
2022 3 82+13+52
*/
/*
语法
窗口函数 over(partiton by 分组 [order by 排序字段  子窗口 ])
年累计销量
大窗口 年
小窗口的范围  从大窗口的第一个 到 当前行
指定小窗口 两种指定方式
    rows  根据行
    range 根据范围执行
当前行  current row
前n行  n preceding
后n行  n following
窗口的上边界  该分区的第一行   unbounded preceding
窗口的下边界  该分区的最后一行  unbounded following
rows

*/
select *,
    sum(sales)
    over (partition by yearly
         order by monthly
         rows between unbounded preceding and current row ) as '每年累计销量'
    from ym_sales;

# 子窗口不指定 默认是从该分区的第一行 到当前行
select *,
    sum(sales)
    over (partition by yearly
         order by monthly) as '每年累计销量'
    from ym_sales;

月份连续用rows ,不连续用range

-- 求每年中 近3个月的累计销量
-- 近3个月  本月 上月 上上月
-- 近3天    今天 昨天 前天
select * from ym_sales;

select *,
       sum(sales)
        over (partition by yearly
             order by monthly
             rows between 2 preceding and current row ) as '近3个月'
    from ym_sales;

-- 如果月份不连续
delete from ym_sales where monthly = 6;
select * from ym_sales;

-- 求每年近3个月的销量和  7月的时候 5+6+7的销量和
-- rows 指定行数的范围 如果月份断了 行数来说 没有变化
-- 以下代码有问题
select *,
       sum(sales)
        over (partition by yearly
             order by monthly
             rows between 2 preceding and current row ) as '近3个月'
    from ym_sales;

-- 解决问题方法
-- 不能用行数来限制子窗口  而是用月份的数据范围 来限定子窗口  7 range
select *,
       sum(sales)
        over (partition by yearly
             order by monthly
             range between 2 preceding and current row ) as '近3个月'
    from ym_sales;

区的第一行 到当前行
select *,
sum(sales)
over (partition by yearly
order by monthly) as ‘每年累计销量’
from ym_sales;


月份连续用rows ,不连续用range

– 求每年中 近3个月的累计销量
– 近3个月 本月 上月 上上月
– 近3天 今天 昨天 前天
select * from ym_sales;

select *,
sum(sales)
over (partition by yearly
order by monthly
rows between 2 preceding and current row ) as ‘近3个月’
from ym_sales;

– 如果月份不连续
delete from ym_sales where monthly = 6;
select * from ym_sales;

– 求每年近3个月的销量和 7月的时候 5+6+7的销量和
– rows 指定行数的范围 如果月份断了 行数来说 没有变化
– 以下代码有问题
select *,
sum(sales)
over (partition by yearly
order by monthly
rows between 2 preceding and current row ) as ‘近3个月’
from ym_sales;

– 解决问题方法
– 不能用行数来限制子窗口 而是用月份的数据范围 来限定子窗口 7 range
select *,
sum(sales)
over (partition by yearly
order by monthly
range between 2 preceding and current row ) as ‘近3个月’
from ym_sales;


;