Mysql基础

数据库的好处

1.可以持久化数据到本地
2.结构化查询

数据库常见概念

1.DB
数据库,存储数据的容器
2.DBMS
数据库管理系统,又称为数据库软件或数据库产品,用于创建和管理DB
3.SQL
结构化查询语言,用于和数据库通信,不是某个数据库特有的,而是几乎主流数据库软件通用的

数据库存储数据的特点

1.数据存放到表中,表再放到库中
2.一个库中可以有多张表,每个表具有唯一的表名来标识自己
3.表中一个或多个列,列又称为‘字段’,相当于‘属性’
4.表中每一行数据相当于‘对象’

参数注释

在这里插入图片描述

基础查询

# 显示表结构,查询全部数据
DESC departments;
select * from departments;

# 基础查询语法
select 查询列表 from 表名;

1.查询列表可以是:表中字段、常量值、表达式、函数
2.查询的结果是一个虚拟的表格

# 查询表中的单个字段
select last_name from employees;

# 查询多个字段
select last_name,salary from employees;

# 查询所有字段
select * from employees;

# 与关键字冲突用着重号 ` (1旁边那个)
select `name` from xxx

# 查询常量值
select 100;
select 'john';

# 查询表达式
select 100%98;

# 查询函数
select version();

# 起别名
1.select 100/98 as num1,100*2 as num2 from employees;
2.select 100/98 num1,100*2 num2 from employees;

# 别名中有空格要加引号
select 100 as 'num ber';

# 去重
select DISTINCT manager_id from employees

# 加号的作用+
# sql中+只能作为运算符,字符型会试图转为数字进行运算
# 成功会运算如'123'+90=213,不成功则字符型为0如'john'+90=90
select null+0; 	只要一个为null就为null

# 连接多个字段 concat(... , ...)
SELECT CONCAT(last_name,email) from employees

# 显示employees全部列,各列直接用逗号隔开,表头为out_put
SELECT CONCAT(last_name,',',email,',',IFNULL(salary,0)) from employees

# 若有列存在null转为0
select IFNULL(salary, 0) as sal from employees;

条件查询

# 条件查询语法
select 查询列表 from 表名 where 筛选条件;

# 分类
1.按条件表达式筛选:<,>,=,<>(不等于),<=,>=
2.按逻辑表达式筛选:and,or,not
3.模糊查询:like,between and,in,is null,is not null

# 按条件表达式筛选
SELECT salary from employees	where salary>100

# 按逻辑表达式筛选
SELECT salary from employees	where salary>100 and salary<5000

# 模糊查询
like:一般和通配符一起使用
通配符:% 任意多个字符,包含0个	
	   _ 任意单个字符
# 包含字符a
SELECT * from employees	where last_name like '%a%'
# 第三个字符为e,第五个字符为a
SELECT * from employees	where last_name like '__e_a%'
# _数字也支持
SELECT * from employees	where manager_id like '1__'
# 第二个字符为_的
1.转义字符
SELECT * from employees	where last_name like '_\_%'
2.自定义转义字符
SELECT * from employees	where last_name like '_$_%' ESCAPE '$'

# between and 
这是闭区间,而且不能between 5000 and 100
SELECT * from employees	where salary BETWEEN 100 and 5000

# in
in列表的值类型必须一致或兼容(如字符->数字)
SELECT * from employees	where job_id in ('AD_VP','PU_MAN')

# is null/is not null
SELECT * from employees	where commission_pct is NULL
SELECT * from employees	where commission_pct is not NULL
# 不可以=或<>等:SELECT * from employees	where commission_pct = NULL

# 安全等于	<=>
SELECT * from employees	where commission_pct <=> NULL
SELECT * from employees	where commission_pct <=> 0.9

# 查询job_id不为IT的
SELECT * from employees	where not(job_id like 'IT%')

排序查询

# 排序查询语法(默认升序)
# order by一般放在语句最后面,limit子句除外
select 查询列表 from 表名 order by 排序列表 asc|desc

# 从高到低(降序)
SELECT * from employees	ORDER BY salary DESC

# 从低到高(升序)
SELECT * from employees	ORDER BY salary ASC

# 按表达式排序
SELECT *,salary*12*(1+IFNULL(commission_pct,0)) as 年薪
from employees ORDER BY salary*12*(1+IFNULL(commission_pct,0))

# 按别名排序
SELECT *,salary*12*(1+IFNULL(commission_pct,0)) as 年薪
from employees ORDER BY 年薪	# 年薪不用加引号

# 按函数排序
SELECT *,LENGTH(last_name) as 长度
from employees ORDER BY LENGTH(last_name)

# 先按工资排序,再按编号排序
SELECT *
from employees ORDER BY salary ASC,employee_id desc
# 先按工资升序排列,然后工资相同的按编号降序排列

常见函数

# 语法
select 函数名(实参列表) [from 表名]

# 单行函数(字符函数)
concat,length,ifnull等
concat:拼接字符
length:获取参数值的 字节 个数
upper、lower:改变大小写

substr、substring:注意:索引从1开始
# 截取指定索引后的字符
SELECT SUBSTR('我爱python',3)	# python
# 截取指定 字符 长度
SELECT SUBSTR('我爱python',1,1)	# 我(str,索引,长度)
SELECT SUBSTR('我爱python',1,2)	# 我爱
# 首字母大写然后拼接其他小写
SELECT CONCAT(UPPER(SUBSTR(last_name,1,1)),LOWER(SUBSTR(last_name,2)))
FROM employees

instr:子串的起始索引
SELECT INSTR('我爱python','python')	# 3

trim:去前后重复
select TRIM('   python   ')	# python(去空格)
SELECT TRIM('a' from 'aaaapythaaonaaa')	# pythaaon(去掉前后a)

lpad:左边填充
select LPAD('python',10,'*')	# ****python

rpad:右边填充

replace:替换
SELECT REPLACE('aaaapython','a','b')	# bbbbpython


# 数学函数
round:四舍五入
select ROUND(1.65)	# 2
select ROUND(1.657,2)	# 保留小数点两位1.66

ceil:向上取整,返回>=该参数的最小整数
select ceil(1.02)	# 2

floor:向下取整,返回<=该参数的最大整数

truncate:截断
select truncate(1.6999,1)	# 保留小数点一位1.6

mod:取余

# 日期函数
now:当前系统日期时间
curdate:返回当前日期,不包括时间
curtime:返回当前时间,不包括日期
year():年	month():月		monthname():月的英文

str_to_date:将日期格式的字符转换成指定格式的日期
SELECT STR_TO_DATE('1998-3-2','%Y-%c-%d')	# 1998-03-02
# 查询入职日期为1992-4-3的人
SELECT * from employees WHERE hiredate = STR_TO_DATE('4-3 1992','%c-%d %Y')

date_format:将日期转为字符
# 查询有奖金的员工名和入职日期(xx月/xx日 xx年)
SELECT last_name,DATE_FORMAT(hiredate,'%m月/%d日 %y年') from employees 
where commission_pct is not null

# 日期减法
SELECT DATEDIFF(NOW(),'1998-11-1')	# 7794

在这里插入图片描述

其他函数

select version()
select database()
select user()

流程控制函数

# if函数:三元运算符
SELECT IF(10>5,'大','小')	# 大

# case函数:
1.switch case效果
case 要判断的变量或表达式
when 常量1 then 要显示的值1或语句1;
when 常量2 then 要显示的值2或语句2;
...
else 要显示的值n或语句n;
end

SELECT salary 工资,department_id,
case department_id
when 20 then salary*1.1
when 30 then salary*1.2
when 40 then salary*1.3
else salary
end as 新工资
from employees

2.类似多重if
case 
when 条件1 then 要显示的值1或语句1;
when 条件2 then 要显示的值2或语句2;
...
else 要显示的值n或语句n;
end

SELECT salary,	# 注意有逗号
case
when salary>20000 then 'A'
when salary>30000 then 'B'
when salary>40000 then 'C'
else 'D'
end as 等级
from employees

# 分组函数:做统计用的,又称为聚合函数、统计函数、组函数
sum:求和
avg:平均数
max:最大值
min:最小值
count:计数

select sum(salary), avg(salary), min(salary), max(salary), count(salary) from employees;

以上分组函数都忽略Null#count函数
select count(*) from employees;	# 统计行数,只要一行中有不为null的就+1

# 和分组函数一起使用,要group by

分组查询

# 语法
select 分组函数,from 表名
[where 筛选条件]
group by[order by 子句]

# 查询每个工种最高工资
select max(salary),job_id
from employees group by job_id

# 查询邮箱中含有a,每个部门平均工资
select AVG(salary),department_id
from employees 
where email like '%a%'
group by department_id

# 查询人数大于2的部门
SELECT count(*),department_id
FROM employees
#where count(*)>2	where查询表中数据,count(*)不在表中,不能这样用
GROUP BY department_id

首先我们上面的代码可以得出各部门的人数,我们可以根据这个表,再筛选人数大于2的:having子句
SELECT count(*),department_id
FROM employees
GROUP BY department_id
HAVING COUNT(*)>2

# 查询每个工种有奖金的最高工资>12000的工种编号和工资
SELECT MAX(salary), job_id
FROM employees
WHERE commission_pct is not null	# commission在表中,可以这样查
GROUP BY job_id
HAVING MAX(salary)>12000

# 分组函数做条件一定在having中
# 能用where筛选就用where筛选
# group by和having也支持别名,where不支持别名

# 分组函数都可以搭配distinct去重
select count(distinct 列名) from# group by也可以接表达式或函数
group by length(last_name)
# 多个字段分组
group by job_id, depatrment_id

# 查询每个部门每个工种员工平均工资,并按平均工资>10000高到低排序
SELECT avg(salary),department_id,job_id
from employees
WHERE department_id is not null
GROUP BY department_id,job_id
having avg(salary)>10000
ORDER BY avg(salary) DESC

连接查询(sql92语法)

又称多表查询,当查询的字段来自多个表时,就会用到连接查询

笛卡尔乘积
当查询多个表时,没有添加有效的连接条件,导致多个表所有行实现完全连接
表1 m行 表2 n行 结果=mxn行
发生原因:没有有效的连接条件
如何避免:添加有效的连接条件

分类:
按功能分:
1.内连接:等值连接、非等值连接、自连接
2.外连接:左外连接,右外连接、全外连接
3.交叉连接

一、等值连接(n表连接,至少需要n-1个连接条件)

# 查询女神名对应的男神名
select name,boyname from beauty,boys
where beauty.boyfriend_id=boys.id

# 为表起别名
select e.last_name,e.job_id,j.job_title 	# 同列名的要指明表
from employees as e,jobs as j
where e.job_id=j.job_id and e.salary>10000
# 注意:如果起了别名,就不能用原来的名字去select

select department_name,city	# 没重名的可以不指明表
from departments as d,locations as l
WHERE d.location_id=l.location_id and city like '_o%'

# 查询有奖金的部门的部门名和其领导编号和该部门的最低工资
select MIN(salary),department_name,d.manager_id
from departments as d,employees as e
where commission_pct is not null and d.department_id=e.department_id
GROUP BY d.department_id,d.manager_id	# 无法确定name和id一一对应就都group by

# 查询每个国家下的部门个数大于2的国家编号
SELECT country_id,COUNT(*)
from locations l,departments d
where d.location_id=l.location_id
GROUP BY country_id
HAVING COUNT(*)>2

二、非等值连接
在两个表中找,但不等于

# 查询员工的工资和工资级别
select salary,grade_level 
from employees as e,job_grades as j
where salary BETWEEN lowest_sal and highest_sal

三、自连接
在同一张表中查找(一张表当两张表用)

# 查询员工名和上级名字
select e.last_name,e.employee_id,m.last_name,m.employee_id
from employees as e,employees as m
where e.employee_id=m.manager_id
# e当员工表,m当领导表,在员工表中找出man_id然后到领导表中匹配emp_id
# 其实就是一张表

SQL99语法

# 语法				  执行顺序
select 查询列表 			 7.
from1 别名 【连接类型】 1.
join2 别名			 2.
on 连接条件				 3.where 筛选条件】		 4.group by5.having6.order by8.limit9.

连接类型分类:
1.内连接:inner
2.外连接:左外:leftouter】
	 	  右外:rightouter】
	 	  全外:fullouter3.交叉连接:cross	 	  

内连接(两个表交集)

等值连接
inner可以省略

select last_name,job_title
from employees e 
INNER JOIN jobs j
on e.job_id=j.job_id
where last_name like '%e%'
------------------------------------------------
select COUNT(*),city
from departments d
INNER JOIN locations l
on d.location_id=l.location_id
GROUP BY city
HAVING COUNT(*)>3
-------------------------------------------------
select last_name,department_name,job_title
from employees e
INNER JOIN departments d on e.department_id=d.department_id
INNER JOIN jobs j on e.job_id=j.job_id
ORDER BY department_name DESC

非等值连接

SELECT salary, grade_level
from employees e
INNER JOIN job_grades g
on salary BETWEEN lowest_sal AND highest_sal

SELECT grade_level,COUNT(*)
from employees e
INNER JOIN job_grades g
on salary BETWEEN lowest_sal AND highest_sal
GROUP BY grade_level
HAVING COUNT(*)>20
ORDER BY COUNT(*) DESC

自连接

SELECT e.last_name,m.last_name
from employees e
JOIN employees m
on e.manager_id=m.employee_id

外连接(一个表中有另外一个表没有)

特点:

  1. 外连接的查询结果为主表中的所有记录
    如果从表中有和他匹配的,则显示匹配的值
    如果从表中没有和他匹配的,则显示null
    外连接查询结果 = 内连接结果 + 主表中有而从表中没有的记录

  2. 左外连接:left join 左边的是主表
    右外连接:right join右边的是主表

  3. 左外和右外交换两个表顺序,结果一样

# 左外连接
# 查询男朋友不在男生表中的女生名
select b.name
from beauty b
left join boys bo
on b.boyfriend_id=bo.id
where bo.id is null	# id是主键,不为null,所以为空的就是男朋友不在男生表中的

#右外连接
select b.name
from boys bo
right join beauty b
on b.boyfriend_id=bo.id
where bo.id is null	

# 查询哪个部门没有员工
select d.*,employee_id
from departments d
LEFT JOIN employees e
on e.department_id=d.department_id	# 到此每个员工和部门匹配了
where e.employee_id is null	# 找员工号为null的即没有员工

# 查询哪个城市没有部门
SELECT country_id,department_id
from locations l
LEFT JOIN departments d
on d.location_id=l.location_id
where department_id is null

# 全外连接=内连接结果+表1有表2没有的+表2有表1没有的

交叉连接(笛卡尔乘积)

select b.*.bo.*
from beauty b
full join boys bo
# beauty 11行 	boys 4行	结果44行

在这里插入图片描述
在这里插入图片描述

# 查询部门名为SAL或IT的员工信息
SELECT e.*,department_name
from departments d	# 以department为主表,因为部门中可能没员工(主表有的从表没有)
LEFT JOIN employees e
on e.department_id=d.department_id
where department_name in ('IT','Sal')

子查询

出现在其他语句中的select语句,称为子查询或内查询
外部的查询语句称为主查询或外查询

分类:
1.子查询出现的位置:

  • select后:仅支持标量子查询
  • from后:支持表子查询
  • where或having后:标量子查询(单行)、列子查询(多行)、行子查询
  • exists后(相关子查询):表子查询

2.按结果集的行列数不同:

  • 标量子查询(结果集只有一行一列)
  • 列子查询(结果集只有一列多行)
  • 行子查询(结果集有一行多列)
  • 表子查询(结果集一般为多行多列)

一、where或having后

特点:
1.子查询都放在括号内
2.子查询一般放在条件的右侧
3.单行子查询一般搭配单行操作符使用:>,<,<>
4.多行子查询一般搭配多行操作符使用:inany/someall

# 标量子查询(单行子查询)
SELECT *
from employees
WHERE salary>(
	SELECT salary
	from employees
	where last_name = 'abel'
)
---------------------------------
SELECT last_name,job_id,salary
from employees
where salary=(
	SELECT MIN(salary)
	FROM employees
)
---------------------------------
# having后
SELECT MIN(salary),department_id
from employees
GROUP BY department_id
HAVING MIN(salary)>(
	SELECT MIN(salary)
	FROM employees
	where department_id=50
	GROUP BY department_id
)

# 非法使用标量子查询情况:
SELECT MIN(salary),department_id
from employees
GROUP BY department_id
HAVING MIN(salary)>(
	SELECT salary	# 结果不为一行一列即单行,与单行操作符冲突
	FROM employees
	where department_id=50
	GROUP BY department_id
)

# 列子查询
SELECT last_name
from employees
where department_id in (
	SELECT department_id	# 多行一列
	from departments
	where location_id in (1400,1700)
)

select *
from employees
where salary<ANY(
	select salary
	from employees
	where job_id='IT_PROG'
	)
可改为max:
select *
from employees
where salary<(
	select max(salary)
	from employees
	where job_id='IT_PROG'
	)

# 行子查询
# 查询员工编号最小并且工资最高的员工信息
select *
from employees
where emp_id=(
	select min(emp_id)
	from employees
)and salary=(
	select max(salary)
	from employees
)
两个等号时可以用行子查询
select *
from employees
where (emp_id,salary)=(
	select min(emp_id),max(salary)
	from employees
)

在这里插入图片描述
a>any() ----> a>min()
a>all() ------> a>max()

二、select后

# 查询每个部门的员工个数
SELECT d.*,(
	select COUNT(*)	# 没有员工的部门是0,因为统计只统计了有员工的部门
	from employees e
	where e.department_id=d.department_id
)
from departments d 

与其他对比
# 外连接查询	
SELECT d.*,COUNT(employee_id)	# 不要count(*),否则没有员工的会记为1,因为数了那一行
from departments d
LEFT JOIN employees e
on d.department_id=e.department_id
GROUP BY department_id

# 内连接和分组查询只能统计有员工的部门人数

三、from后

# 查询每个部门的平均工资和工资等级
SELECT ag_dep.*,grade_level
from (
	SELECT AVG(salary) ag,department_id
	from employees
	GROUP BY department_id
) ag_dep
INNER JOIN job_grades j	
on ag_dep.ag BETWEEN lowest_sal and highest_sal

# 查询各部门中工资比本部门平均工资高的员工姓名工资
select last_name,salary,e.department_id
from employees e
inner join (
	select avg(salary) ag,department_id
	from employees
	group by department_id
) ag_dep
on e.department_id=ag_dep.department_id
where e.salary>ag_dep.ag

四、exists后

select exists(select job_id from employees)	# 1(是否存在,1则存在,0不存在)

# 查询有员工的部门名
select department_name
from department d
where exists(
	select *
	from employees e
	where d.department_id=e.department_id
)exists的都可以用in
select department_name
from departments d
where d.department_id in(
	select department_id
	from employees
)

分页查询

当要显示的数据,一页显示不全,需要分页提交sql请求

# 语法
放在最后:limit offset,size
offset:要显示条目起始索引(索引从0开始)
size:要显示的条目个数

公式:要显示的页数 page,每页的条目数 size
limit (page-1)*size,size;

# 查询前五条员工信息
select * from employees limit 0,5

测试

# 查询所有学生的邮箱用户名(@前)
select substr(email,1,instr(email.'@')-1) from stuinfo

# 查询平均工资最低的部门信息和平均工资
SELECT d.*,ag
from departments d
INNER JOIN(
SELECT AVG(salary) ag,department_id
from employees
GROUP BY department_id
) sa_dep
on d.department_id=sa_dep.department_id
ORDER BY ag ASC
LIMIT 0,1

方法二:
SELECT e.department_id,AVG(salary) avgsal
FROM employees e
GROUP BY e.department_id
HAVING avgsal=(
SELECT MIN(t.avgsal) minsal
from(
SELECT department_id,AVG(salary) avgsal
FROM employees
GROUP BY department_id) as t
)

# 各部门最高工资中最低的那个部门的最低工资
SELECT MIN(salary)
FROM employees
where department_id=(
SELECT e.department_id
FROM employees e
GROUP BY e.department_id
HAVING MAX(salary)=(
	SELECT MIN(t.maxsal) minsal
	from(
		SELECT department_id,max(salary) maxsal
		FROM employees
		GROUP BY department_id) as t
))

联合查询

要查询的结果来自多个表,且中间没连接关系
两个查询结果列数必须一致,结果每一列类型要一致

union:将多条查询语句的结果合并为一个结果

select * from employees where salary>100 or dep_id>90
等于
select * from employees where salary>100
union
select * from employees where dep_id>90

# 例
select id,name from tcn where sex=1
union
select tid,tname from tus where tsex=1

# union会自动去重
如果想保留重复项用:
union all

DML语言

增 insert
删 delete
改 update

一、插入
插入的值类型要和列的类型一致或兼容

# 语法一
insert into 表名(列名,...values (值,...insert into beauty(id,name,sex,photo,phone)
values (13,'john','女',NULL,'123456')	# 照片是blob类型,插入的时候先用null代替

# 可以为null的列如何插入值
1.null占位
2.直接列都不写
insert into beauty(id,name,sex,phone)
values (13,'john','女','123456')

# 列数和值个数必须一致
# 列可以不写,默认所有列,顺序和表中一致


# 语法二
insert into 表名
set 列名=值,列名=...

insert into beauty
set id=19,name='mike'

# 对比
values支持插入多行,set不支持
insert into beauty
values (13,'john','女','123456')
,(14,'jo','女',NULL,'123456')

values支持子查询,set不支持
insert into beauty(id,name,sex)
select id,boyname,'男'
from boys where id<3

二、修改

1.修改单表的记录
update 表名
set=值,列=...
where 筛选条件

update beauty
set phone='123456789',sex='男'
where name like '唐%'


2.修改多表的记录
sql99语法
update1 别名
inner|left|right join2 别名
on 连接条件
set=,...
where 筛选条件

# 修改john女朋友的手机号114
update boys b
inner join beauty b
on bo.id=b.boyfriend_id
set b.phone='114'
where bo.boyname='john'

# 修改没有男朋友的女生男朋友编号为2
update boys bo
right join beauty b 
on bo.id=b.boyfriend_id
set b.boyfriend_id=2
where b.id is null

三、删除

方法一
delete from 表名
where 筛选条件

1.单表的删除
# 删除手机号9结尾的女生
delete from beauty where phone like '%9'

2.多表的删除(级联删除)
delete 别名(删表1的写表1别名,删表2的写表2别名)
from1 别名
innerjoin2 别名
on 连接条件
where 连接条件
and 筛选条件

# 删除john女朋友信息
delete b
from beauty b
inner join boys bo
on bo.id=b.boyfriend_id
where bo.boyname='john'

# 删除mike和他女朋友信息
delete b,bo
from beauty b
inner join boys bo
on bo.id=b.boyfriend_id
where bo.boyname='mike'

方法二
truncate table 表名
注意不能加where,其实就是个清空表

# 对比❤
# delete可以加where,truncate不能

# truncate删除效率高一点

# 假如要删除的表中有自增长列,
# 如果用delete删除后,再插入数据,自增长列的值从断点开始,
# 而truncate删除后,再插入数据,自增长列的值从1开始

# delete删除有返回值,truncate删除没有返回值

# truncate删除不能回滚,delete删除可以回滚

DDL语言

数据定义语言,库和表的管理
创建 create
修改 alter
删除 drop

一、库的管理

# 创建库
create database 库名;

create database books;

增加容错:
create database if not exists books;

# 修改库的字符集
alter database books character set gbk;

# 库的删除
drop database if exists books;

二、表的管理

# 表的创建
create table 表名(
	列名 列的类型 (长度) (约束),
	...
	列名 列的类型 (长度) (约束)
);

create table book(
	id int,# 编号
	bname varchar(20), # 书名	
	price double, # 价格
	authorid int, # 作者编号
	publishDate datetime # 出版时间
)

create table author(
	id int,
	au_name varchar(20)
)


# 表的修改
# 修改列名
alter table book change column publishDate pubDate datetime; # 要加类型

# 修改列的类型或约束
alter table book modify column pubDate timestamp;

# 添加列
alter table author add column annual doublefirst|after 字段名】(添加列的位置);

# 删除列
alter table author drop column annual;

# 修改表名
alter table author rename to book_author;


# 表的删除
drop table book_author;


# 表的复制
1.仅复制表的结构
create table copy like author;

2.复制表的结构+数据
create table copy2
select * from author

可以跨库
create table copy2
select * from employee.author

3.复制部分数据
create table copy3
select * from author
where nation='china'

4.仅复制某些字段
create table copy4
select * from author where 0;

数据类型

分类:

  • 数值型:整型、小数(定点数、浮点数)
  • 字符型:较短的文本(char、varchar)、较长的文本(text、blob(较长的二进制数据))
  • 日期型

类型选择原则:越简单越好,能保存数值的类型越小越好

一、整型
在这里插入图片描述
如何设置有符号和无符号
默认有符号,设置无符号用unsigned

create table tab_int(
	t1 int,
	t2 int unsigned	# 无符号
)

insert into tab_int values(-123)	# 成功,有符号
insert into tab_int values(-123,-123)# 报错

# 插入的值大于整型范围会报out of range并且填入临界值

# 如果不设置长度会有默认长度
用t1 int zerofill可以让输出的数字零填充如000123,并且如果用了zerofill就是无符号

二、小数
在这里插入图片描述

create table tab_float(
	t1 float(5,2),
	t2 decimal(5,2)
)

insert into tab_float values(123.45,123.45)
5:整数部分+小数部分长度
2:小数部分长度
超过范围则填入临界值

floatdouble会根据插入数字的精度调整精度
decimal默认为(10,0)

定点型精度较高,如果要求插入数值的精度较高如货币运算等则考虑使用

三、字符型
注意是字符数
在这里插入图片描述
char是给固定长度空间
varchar是根据输入分配空间

enum(‘a’,‘b’,‘c’) 输入只能输入列表中有的之一,不区分大小写
set(‘a’,‘b’,‘c’) 输入可以输入列表中有的任意,不区分大小写

四、日期型
在这里插入图片描述
在这里插入图片描述

常见约束

**含义:**一种限制,用于限制表中的数据,为了保证表中的数据的准确和可靠性

分类:

  1. NOT NULL:非空,用于保证该字段的值不能为空。比如姓名、学号等
  2. DEFAULT:默认,用于保证该字段有默认值。比如性别
  3. PRIMARY KEY:主键,用于保证该字段的值具有唯一性,并且非空。比如学号、员工编号等
  4. UNIQUE:唯一,用于保证该字段的值具有唯一性,可以为空。比如座位号
  5. CHECK:检查约束【mysql中不支持】比如年龄、性别
  6. FOREIGN KEY:外键,用于限制两个表的关系,用于保证该字段的值必须来自于主表的关联列的值。
    在从表添加外键约束,用于引用主表中某列的值。比如员工表的部门编号、工种编号

添加约束的时机:

  1. 创建表时
  2. 修改表时

约束的添加分类:
列级约束:
六大约束语法上都支持,但外键约束没有效果

表级约束:
除了非空、默认,其他的都支持

create table 表名(
字段名 字段类型 列级约束,
字段名 字段类型,
表级约束

一、创建表时添加约束
1.添加列级约束:直接在字段名和类型后追加约束类型即可

create database students

create table stuinfo(
	id int primary key,
	stuname varchar(20) not null,
	sex char(1) check(sex='男' or sex='女')# check没用
	seat int unique NOT NULL, # 可以加多个约束,空格隔开
	age int default 18,
	majorid int references major(id) # 列级外键没用
)

create table major(
	id int primary key,
	majorname varchar(20)
)

show index from stuinfo; # 查看所有索引,包括主键、外键、唯一

2.添加表级约束:在各个字段的最下面
constraint 约束名 约束类型 (字段名)

create table stuinfo(
	id int,
	stuname varchar(20),
	sex char(1),
	seat int,
	age int,
	majorid int,
	[constraint xx] primary key (id),# 主键
	[constraint yy] unique (seat),# 唯一
	constraint fk_stuinfo_major foreign key (majorid) references major(id)	# 外键
# yy,fk_stuinfo_major是key name
# fk外键 stuinfo当前表名 major主表名
# constraint xx可以省略
)

※主键和唯一的区别:※

保证唯一性是否允许为空一个表中可以有多少个是否允许组合
主键×至多有1个√,但不推荐
唯一可以有多个√,但不推荐

唯一键:空值也只能有一个

组合:
primary key(id,stuname) 表示这两列组合成一个主键

这样没问题
insert into stuinfo values (1,‘john’)
insert into stuinfo values (2,‘john’)

这样也没问题
insert into stuinfo values (1,‘john’)
insert into stuinfo values (1,‘lily’)

这样有问题即组合主键都重复
insert into stuinfo values (1,‘john’)
insert into stuinfo values (1,‘john’)

外键

  1. 要求在从表设置外键关系
  2. 从表的外键列的类型和主表的关联列的类型要求一致或兼容,名称无要求
  3. 主表中的关联列必须是一个key(一般是主键或唯一)
  4. 插入数据时,先插入主表,再插入从表。删除数据时,先删除从表,再删除主表
一定要先删主表怎么办
如stu里的majorid与major里的id关联,我要删major里的id=3
先把原来的外键删除,然后再添加如下外键

1.级联删除(添加外键时设置)
删id=3的同时把stu里majorid=3的信息一起删除
alter table stu add constraint fk_stu_major foreign key(majorid) references major(id) on delete cascade;
delete from major where id=3;	# 此时就能删了

2.级联置空(添加外键时设置)
alter table stu add constraint fk_stu_major foreign key(majorid) references major(id) on delete set null;


二、修改表时添加约束
create table stuinfo(
id int,
stuname varchar(20),
sex char(1),
seat int,
age int,
majorid int

1.添加非空约束
alter table stuinfo modify column stuname varchar20NOT NULL

2.添加默认约束
alter table stuinfo modify column age int default 18;

3.添加主键
# 列级约束(修改列)
alter table stuinfo modify column id int primary key
# 表级约束
alter table stuinfo add primary key(id)

4.添加唯一
alter table stuinfo modify column seat int unique

5.添加外键
alter table stuinfo add [constraint fk_stuinfo_major] foreign key (majorid) references major(id)

总结
1.添加列级约束
alter table 表名 modify column 字段名 字段类型 新约束

2.添加表级约束
alter table 表名 add [constraint 约束名] 约束类型(字段名)

三、修改表时删除约束

1.删除非空约束
alter table stuinfo modify column stuname varchar20# 不写约束就行了

2.删除唯一
alter table stuinfo drop index 约束名

3.删除外键
alter table stuinfo drop foreign key fk_stuinfo_major

标识列

又称为自增长列
含义:可以不用手动的插入值,系统提供默认的序列值

一、创建表时设置标识列
特点:

  1. 标识列必须和主键搭配?不一定,但要求是一个key
  2. 一个表中可以有几个标识列?至多一个
  3. 标识列的类型只能是数值型
  4. 标识列可以设置步长,可以通过 手动插入值 修改初始值
create table tab_identity(
	id int primary key auto increment,	# 自增长列
	name varchar(20)
)

insert into tab_identity valuesnull'john')

设置步长:
set auto_increment_increment=3

二、修改表时设置标识列

alter table tab_identity modify column id int primary key auto increment

三、删除标识列

alter table tab_identity modify column id int 

TCL语言

transaction control language 事务控制语言

事务:一个或一组sql语句组成一个执行单元,这个执行单元要么全部执行,要么全部不执行

事务的ACID属性:

  1. 原子性(Atomicity):原子性是指事务是一个不可分割的工作单位,事务中的操作要么全部发生,要么都不发生
  2. 一致性(Consistency):事务必须使数据库从一个一致性状态变换到另外一个一致性状态,以后查看数据库这些数据不会改变,是一致的
  3. 隔离性(Isolation):事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰
  4. 持久性(Durability):持久性是指一个事务一旦被提交,它对数据库中数据的改变是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响

事务的创建
隐式事务:事务没有明显的开启或结束的标记,比如insert,update,delete语句(自动提交功能为开启)

显式事务:事务具有明显的开启或结束的标记,前提:必须先关闭自动提交功能

1.开启事务
set autocommit=0start transaction;(可选的)

2.编写事务中的sql语句
selectinsertupdatedelete

3.结束事务
commit;提交事务
或
rollback;回滚事务(可以理解为事务所处理的放在内存中,取决于是否提交,如果回滚就释放内存,什么都不变)
或
savepoint+节点 保存点(搭配rollback使用)

在这里插入图片描述
隔离级别
在这里插入图片描述
在这里插入图片描述
改变隔离级别
要用命令行

# 查看隔离级别
select @@tx_isolation
# 设置当前数据库隔离级别
set session transaction isolation level 隔离级别
#设置数据库系统全局隔离级别
set global transaction isolation level 隔离级别

在这里插入图片描述
没提交事务,但读到了john(脏读),再读一次(不可重复读)变成了张无忌(幻读)

脏读:开始一个事务T1,修改一个数据,但没有提交。另外一边开始一个事务T2,读取数据,发现变成了修改后的数据,这就是脏读。
不可重复读:开始一个事务T1,修改一个数据,但没有提交。另外一边开始一个事务T2,读取数据,然后T1提交了,T2读取这个数据,发现数据变了,这就是不可重复读。
若要可重复读,就是T2读取的数据都没变,然后提交,开始新事务T3,T3再读取发现数据变了。
幻读:开始一个事务T1,读取数据。另外一边开始一个事务T2,增加一列数据,然后T2提交了,T1读取这个数据,发现数据多了一列,这就是幻读。

视图

含义:本身是虚拟表,它的数据来自于表,通过执行时动态生成,是临时的,和普通表一样使用,只保存了sql逻辑,不保存查询结果。

用途:
1.多个地方用到同样的查询结果
2.该查询结果使用的sql语句比较复杂

封装一个查询学生名字和专业名的视图
create view v1
as
select stuname,majorname from students s
inner join major m
on s.majorid=m.id

select * from v1 where stuname like 'Z%'

# 创建视图
create view 视图名 as 查询语句;

# 查看每个部门平均工资级别
create view v2
as
select avg(salary) ag,department_id from employees
group by department_id

select v2.ag,g.grade_level
from v2 inner join job_grades g
on v2.ag between lowest_sal and highest_sal;

视图好处:

  1. 重用sql语句
  2. 简化复杂sql操作,不必知道它的细节
  3. 保护数据,提高安全性

二、视图的修改

方式一
create or replace view 视图名
as 查询语句;

方式二
alter view 视图名
as 查询语句;

三、视图的删除和查看

# 删
drop view 视图名,视图名,...;
# 查看
DESC 视图名;show create view 视图名\G(命令行里比较好看,\G格式化)

四、视图的更新

create or replace view v1
as ....

# 插入
insert into v1 values('..',...)	# 插入后原始表中也有了

# 修改
update v1 set ... where ...	# 修改后原始表也改了

# 删除
delete from v1 where...	# 原始表也会删

在这里插入图片描述
常量视图就是结果只有一个值的视图

视图和表对比

创建关键字是否实际占用物理空间功能
视图create view只是保存了sql逻辑一般只能查,不能增删改数据
create table保存了数据增删改查

delete和truncate在事务使用时的区别
delete可以回滚,truncate不能回滚

变量

1.系统变量:
由系统提供,不是用户定义,属于服务器层面
全局变量:
作用域:服务器每次启动将为所有的全局变量赋初始值,针对于所有的会话(连接)有效,但不能跨重启
会话变量:
作用域:仅针对当前会话(连接)有效

1.查看所有的系统变量(全局|会话)
show global|session variables;

2.查看满足条件的部分系统变量
show global|session variables like '%char%';

3.查看指定的某个系统变量的值
select @@global|session.系统变量名;

4.为某个系统变量赋值
方式一
set global|session 系统变量名 =;
方式二
set @@global|session.系统变量名 =;

2.自定义变量:
用户变量:
作用域:针对于当前会话(连接)有效,同于会话变量的作用域
应用在任何地方,也就是begin end里面或外面

# 步骤
声明并初始化
set @用户变量名=;
为避免=号歧义
set @用户变量名:=;select @用户变量名:=;

赋值(更新用户变量的值)
方式一:通过setselect,同上
方式二:通过select into
select 字段 into 变量名 from;# 要求查询出来的字段是一个值

使用(查看、比较、运算等)
查看:select @用户变量名;

局部变量:
作用域:仅仅在定义它的begin end中有效
应用在 begin end中的第一句话!!

声明并赋初始值
declare 变量名 类型 default;

赋值
方式一
set 局部变量名=;
set 局部变量名:=;select @局部变量名:=;
方式二
select 字段 into 局部变量名 from;

使用
select 局部变量名;

在这里插入图片描述
在这里插入图片描述

存储过程和函数

类似于方法
含义:一组预先编译好的sql语句的集合,理解成批处理语句
好处:提高代码重用性、简化操作、减少了编译次数和数据库服务器的连接次数,提高了效率

创建语法
create procedure 存储过程名(参数列表)
begin
	存储过程体(一组合法的sql语句)
end
注意:
1.参数列表包含三部分
参数模式		参数名	   参数类型
in			stuname 	varchar20)
参数模式:
IN:该参数可以作为输入,也就是该参数需要调用方法传入值
OUT:该参数可以作为输出,也就是该参数可以作为返回值
INOUT:该参数既可以作为输入也可以作为输出,也就是该参数既需要传入值,又可以返回值

2.如果存储过程中仅仅只有一句话,begin end可以省略

3.存储过程体中的每条sql语句的结尾要求必须加分号。
存储过程的结尾可以使用 delimiter 重新设置
语法:delimiter 结束标记(随便什么符号)


调用语法
call 存储过程名(实参列表);

1.空参列表

# 插入到admin表中五条记录
delimiter $
create procedure myp1()
begin
	insert into admin(username,password) values('join1','0000'),('join2','0000'),('join3','0000'),('join4','0000'),('join5','0000');
end $

# 调用
call myp1() $
# 上面这些必须在命令行中运行

在这里插入图片描述
2.带in模式参数的存储过程

# 根据女生名查询对应的男生信息 
create procedure myp2(IN beautyName varchar(20))
begin
	select bo.*
	from beauty b
	left join boys bo on bo.id=b.boyfriend_id
	where b.name=beautyName;
end $

# 调用
call myp2('lily') $

# 创建存储过程实现用户是否登录成功
create procedure myp3(IN username varchar(20),IN password varchar(20))
begin
	declare result INT default 0;	# 声明变量并初始化
	select count(*) into result	# 赋值
	from admin
	where admin.username = username
	and admin.password = password; # 参数名重复,指明表
	select IF(result>0,'成功','失败'); # 使用
end $

call myp3('john','000') $

在这里插入图片描述
出现这个问题是字符集问题,改下编码

3.带out模式的存储过程

# 根据女生名返回对应的男生名
create procedure myp5(IN beautyName varchar(20),OUT boyName varchar(20))
begin
	select bo.boyName into boyName
	from boys bo
	inner join beauty b on bo.id=b.boyfriend_id
	where b.name=beautyName;
end $

set @bName$	# 定义一个用户变量用于存返回值
call myp5('lily',@bName)$
select @bName$


# 根据女生名返回对应男生名和魅力值
create procedure myp6(IN beautyName varchar(20),OUT boyName varchar(20),OUT userCP int)
begin
	select bo.boyName,bo.userCP into boyName,userCP
	from boys bo
	inner join beauty b on bo.id=b.boyfriend_id
	where b.name=beautyName;
end $

call myp6('lily',@bName,@usercp)$	# 变量直接写进去也行
select @bName,@usercp

4.带inout模式参数的存储过程

# 传入a和b两个值,最终a和b都翻倍并返回
create procedure myp8(inout a int,inout b int)
begin 
	set a=a*2;	# 局部变量赋值
	set b=b*2;
end $

set @m=10$
set @n=20$	# 声明两个用户变量用来存值
call myp8(@m,@n)$
select @m,@n$

存储过程的删除

drop procedure 存储过程名;
# 每次只能删一个

查看存储过程的信息

show create procedure 存储过程名;

函数

含义:一组预先编译好的sql语句的集合,理解成批处理语句
好处:提高代码重用性、简化操作、减少了编译次数和数据库服务器的连接次数,提高了效率

和存储过程的区别
存储过程:可以有0个返回,也可以有多个返回,适合做批处理
函数:只能有1个返回,适合做处理数据后返回一个结果

# 创建语法
create function 函数名(参数列表) returns 返回类型(注意是返回类型)
begin
	函数体
end

注意:
1.参数列表只有两部分 函数名 参数类型
2.如果return语句没有放在函数体的最后也不报错,但不建议
return;
3.函数体中只有一句话可以省略begin end
4.使用 delimiter语句设置结束标记


# 调用
select 函数名(参数列表)

1.无参有返回

# 返回公司员工个数
create function myf1() returns int
begin 
	declare C int default 0;	# 定义局部变量
	select count(*) into C	# 赋值
	from employees;
	return C;	# 注意要return
end $

select myf1()$

2.有参有返回

# 根据员工名返回他的工资
create function myf2(empName varchar(20)) returns double
begin
	set @sal=0; 	# 定义用户变量
	select salary into @sal	# 赋值
	from employees
	where last_name=empName;
	return @sal;
end $

select myf2('ko')$

查看函数

show create function 函数名;

删除函数

drop function myf3(函数名);

流程控制结构

**顺序结构:**程序从上往下依次执行
**分支结构:**程序从两条或多条路径中选择一条去执行
**循环结构:**程序在满足一定条件的基础上,重复执行一段代码

分支结构

1.IF函数
功能:实现简单的双分支
语法:IF(表达式1,表达式2,表达式3)
可以应用在任何地方


2.case结构(作为独立语句)
功能:用于实现
等值判断
语法:case 变量|表达式|字段 when 要判断的值 then 返回值1或语句1;
...
else 返回值n或语句n
end case;

区间判断
语法:case  when 要判断的条件1 then 返回值1或语句1;
...
else 返回值n或语句n;
end case;

特点:
1.可以作为表达式,嵌套在其他语句中使用,可以放在任何地方,begin end中或外
可以作为独立的语句使用,只能放在begin end中

积分result表中有A B C D四列,要求:
1)当A列值大于等于B列时,选择A列否则选择B列
2)当C列值大于等于D列时,选择C列否则选择D列
select (case when A>=B then A else B end) MAX_AB, (case when C>=D then C else D end) MAX_CD from result

2.如果when中的值满足或条件成立,则执行对应的then后面的语句,并且结束case
如果都不满足,则执行else中的语句或值
3.else可以省略,如果else省略了,并且所有when条件都不满足,则返回NULL

# 案例:创建存储过程,根据传入的成绩,来显示等级,比如传入的成绩:90-100,显示A...
create procedure test_case(IN score int)
begin
	case 
	when score>=90 and score<=100 then select 'A';
	when score>=80 then select 'B';
	when score>=60 then select 'C';
	ELSE select 'D';
	end case;
end $

call test_case(90)$


3.if结构
功能:实现多重分支
语法:if 条件1 then 语句1;
elseif 条件2 then 语句2;
...
else 语句n;
end if;
只能应用在begin end# 案例:根据传入的成绩,来显示等级,比如传入的成绩:90-100,返回A...
create function test_if(score int) returns char
begin
	if score>=90 and score<=100 then return 'A';
	elseif score>=80 then return 'B';
	elseif score>=60 then return 'C';
	else return 'D';
	END if;
end $

select test_if(86)$

循环结构

分类:
whilelooprepeat
循环控制:
iterate类似于continue:结束本次循环,继续下一次
leave类似于break:结束当前所在的循环

1.while
语法:
【标签:】while 循环条件 do
	循环体;
end while 【标签】;	# 若要用循环控制语句要加标签

# 案例:根据次数插入到admin表中多条记录(没返回则创建存储过程)
# 无循环控制语句
create procedure pro_while1(IN insertCount int)
begin
	declare i int default 1;
	while i<=insertCount do
		insert into admin(username,password) values ('john','111');
		set i=i+1;
	end while;
end $

call pro_while1(100)$

# 添加leave语句
# 案例:根据次数插入到admin表中多条记录,如果次数>20则停止
create procedure pro_while2(IN insertCount int)
begin
	declare i int default 1;
	a:while i<=insertCount do
		insert into admin(username,password) values ('john','111');
		set i=i+1;
		IF i>20 then leave a;
		end if;
	end while a;
end $

call pro_while2(100)$

# 添加iterate语句
# 案例:根据次数插入到admin表中多条记录,只插入偶数次
create procedure pro_while3(IN insertCount int)
begin
	declare i int default 0;
	a:while i<=insertCount do
		set i=i+1;
		IF MOD(i,2)!=0 then iterate a;
		END if;
		insert into admin(username,password) values ('john','111');
	end while a;
end $

call pro_while3(100)$


2.loop
语法:
【标签:】loop
		循环体;
end loop 【标签】;
可以用来模拟简单的死循环,因为没有循环条件,要结束必须用循环控制


3.repeat
语法:
【标签:】repeat
	 循环体;
until 结束循环的条件
end repeat 【标签】;

总结
在这里插入图片描述
流程控制经典案例

已知表stringcontent
其中字段:
id  自增长
content  varchar(20)
向该表插入指定个数的随机字符串

create table stringcontent(
	id int primary key auto_increment,
	content varchar(20)
);

delimiter $
create procedure test_randstr(IN insertCount int)
begin
	declare i int default 1;	# 定义一个循环变量i,表示插入次数
	declare str varchar(26) default 'abcdefghijklmnopqrstuvwxyz';
	declare startIndex int default 1;	# 代表起始索引
	declare len int default 1;	# 代表截取的字符的长度
	while i<=insertCount do
					# 产生一个随机整数,代表起始索引1-26
		set len=floor(rand()*26+1);
		set startIndex=floor(rand()*26+1);	#产生一个随机整数,代表起始索引1-26
		insert into stringcontent(content) values (substr(str,startIndex,len));
		set i=i+1;	# 循环变量更新
	end while;
end $

call test_randstr(10)$

select * from stringcontent$

其他练习

有一张学生成绩表sc(sno 学号,class 课程,score 成绩),请查询出每个学生的英语、数学的成绩(行转列,一个学生只有一行记录)。
select sno,
sum(if(class='english',score,0)) as english,
sum( if(class='math',score,0) ) as math
from sc
where class in('english','math')
group by sno

窗口函数

参考文献
基本语法

<窗口函数> over (partition by <用于分组的列名>
                order by <用于排序的列名>)

1) 专用窗口函数,包括后面要讲到的rank, dense_rank, row_number等专用窗口函数。
2) 聚合函数,如sum. avg, count, max, min等

因为窗口函数是对where或者group by子句处理后的结果进行操作,所以窗口函数原则上只能写在select子句中。

专用窗口函数rank
在这里插入图片描述

select *,
   rank() over (partition by 班级
                 order by 成绩 desc) as ranking
from 班级表

1)每个班级内:按班级分组
partition by用来对表分组。在这个例子中,所以我们指定了按“班级”分组(partition by 班级)

2)按成绩排名
order by子句的功能是对分组后的结果进行排序,默认是按照升序(asc)排列。在本例中(order by 成绩 desc)是按成绩这一列排序,加了desc关键词表示降序排列。

通过下图,我们就可以理解partiition by(分组)和order by(在组内排序)的作用了。
在这里插入图片描述
窗口函数具备了我们之前学过的group by子句分组的功能和order by子句排序的功能。那么,为什么还要用窗口函数呢?

这是因为,group by分组汇总后改变了表的行数,一行只有一个类别。而partiition by和rank函数不会减少原表中的行数。例如下面统计每个班级的人数。
在这里插入图片描述
partition子句可是省略,省略就是不指定分组,结果如下,只是按成绩由高到低进行了排序:

select *,
   rank() over (order by 成绩 desc) as ranking
from 班级表

在这里插入图片描述
但是,这就失去了窗口函数的功能,所以一般不要这么使用。

专用窗口函数rank, dense_rank, row_number

select *,
   rank() over (order by 成绩 desc) as ranking,
   dense_rank() over (order by 成绩 desc) as dese_rank,
   row_number() over (order by 成绩 desc) as row_num
from 班级表

在这里插入图片描述
rank函数:这个例子中是5位,5位,5位,8位,也就是如果有并列名次的行,会占用下一名次的位置。比如正常排名是1,2,3,4,但是现在前3名是并列的名次,结果是:1,1,1,4。

dense_rank函数:这个例子中是5位,5位,5位,6位,也就是如果有并列名次的行,不占用下一名次的位置。比如正常排名是1,2,3,4,但是现在前3名是并列的名次,结果是:1,1,1,2。

row_number函数:这个例子中是5位,6位,7位,8位,也就是不考虑并列名次的情况。比如前3名是并列的名次,排名是正常的1,2,3,4。

最后,需要强调的一点是:在上述的这三个专用窗口函数中,函数后面的括号不需要任何参数,保持()空着就可以。

聚合函数作为窗口函数

select *,
   sum(成绩) over (order by 学号) as current_sum,
   avg(成绩) over (order by 学号) as current_avg,
   count(成绩) over (order by 学号) as current_count,
   max(成绩) over (order by 学号) as current_max,
   min(成绩) over (order by 学号) as current_min
from 班级表

在这里插入图片描述
如上图,聚合函数sum在窗口函数中,是对自身记录、及位于自身记录以上的数据进行求和的结果。比如0004号,在使用sum窗口函数后的结果,是对0001,0002,0003,0004号的成绩求和,若是0005号,则结果是0001号~0005号成绩的求和,以此类推。

不仅是sum求和,平均、计数、最大最小值,也是同理,都是针对自身记录、以及自身记录之上的所有数据进行计算

比如0005号后面的聚合窗口函数结果是:学号0001~0005五人成绩的总和、平均、计数及最大最小值。

如果想要知道所有人成绩的总和、平均等聚合结果,看最后一行即可。

这样使用窗口函数有什么用呢?

聚合函数作为窗口函数,可以在每一行的数据里直观的看到,截止到本行数据,统计数据是多少(最大值、最小值等)。同时可以看出每一行数据,对整体统计数据的影响

总结

2.窗口函数有以下功能:

1)同时具有分组(partition by)和排序(order by)的功能

2)不减少原表的行数,所以经常用来在每组内排名

3.注意事项

窗口函数原则上只能写在select子句中

4.窗口函数使用场景

1)业务需求在每组内排名,比如:
排名问题:每个部门按业绩来排名
topN问题:找出每个部门排名前N的员工进行奖励

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值