(day03):MySQL函数及多表查询

 注意:开发中函数可以到MySql文档中查找,是函数都需要加().

一:练习

1.新建 教室表
   教室id  主键自增
   课程   非空

2.新建表 person 
   id   主键自增
   名字 非空
   邮箱 唯一
   性别 默认男
   房间编号 关联 教室表 教室id  级联策略 删除父表数据 子表对应数据设置为null 修改父表数据 子表数据一同修改
     
  3.分别插入三条数据   
  
  4.删除父表数据 
    修改父表数据

create table clazzroom(

	cid int primary key auto_increment,
	crouse varchar(20)
);

create table person(
	pid int primary key auto_increment,
	pname varchar(20) not null,
	email varchar(20) unique key,
	sex char default '男',
	roomid int,
	foreign key(roomid) references clazzroom(cid) on delete set null on update cascade
	
);


-- 插入数据向 教室表

insert into clazzroom values(null,"JAVA");
insert into clazzroom values(null,"H5");
insert into clazzroom values(null,"BigData");

select * from clazzroom;

-- 向学生表插入数据

insert into person(pid,pname,email,roomid) values(null,"李白","lb@163.com",1);
insert into person(pid,pname,email,roomid) values(null,"杜甫","df@163.com",2);
insert into person(pid,pname,email,roomid) values(null,"王安石","was@163.com",3);
-- 错误演示
insert into person(pid,pname,email,roomid) values(null,"李商隐","lsy@163.com",6);

select * from person;

-- 删除 cid =1 的数据

delete from clazzroom where cid =1;

-- 修改 将cid =2 的值 改为 cid =6


update clazzroom set cid = 6 where cid = 2;

(二):数学函数

-- 绝对值
select ABS(1),ABS(-1);
-- 向下取整floor()
-- 向上取整 ceil()
select FLOOR(3.6),FLOOR(4.3),CEIL(4.3),CEIL(5.6);
-- 四舍五入
-- round(3.56) 只要整数部分对小数部分四舍五入
select ROUND(3.56);
-- round(小数,整数) 保留整数位小数 对整数位后面的小数 进行四舍五入
select ROUND(3.12345,2);
select ROUND(3.12945,4);
-- 保留指定位数的小数 不会进行四舍五入
select TRUNCATE(3.56,1);
-- 保留0位小数
select TRUNCATE(3.56,0);
-- 开平方
select SQRT(16);
-- x^y
select POW(3,3);

(三):日期函数

-- 3.日期函数
-- 获取当前的年月日 ,时分秒
select CURDATE(),CURTIME();
-- sysdate()执行那一刹那的时间  NOW()获取了一次值之后,第二次获取的是缓存中的
select NOW(),SYSDATE(),SLEEP(5),NOW(),SYSDATE();
-- 获取年  月
select YEAR(NOW()),MONTH(NOW());
-- 获取月份的名字
select MONTHNAME(NOW()),MONTHNAME("2022-2-1");
-- dayofweek 周日是1  weekday 周一是 0
select DAYOFWEEK(NOW()),WEEKDAY(NOW());
-- 返回周几的英文字母
select DAYNAME(NOW());
-- 两个日期之间的差值 select datediff(date1,date2); date1 -date2
select DATEDIFF(NOW(),'2021-11-5');
-- 改变日期
select DATE_ADD(NOW(),interval -1 year);
select DATE_ADD(NOW(),interval 1 year);
select PASSWORD(123456);

(四):其他函数

-- 返回正在操作的数据库
select DATABASE();
-- 返回数据库的版本
select VERSION();
-- 返回正在操作数据库的用户
select USER();
-- 加密方式
select PASSWORD(123456);
select MD5("床前明月光")

(五):流程函数

/*

if(value,t,f) value 真 t 假 f


*/
select * from t_employee;

select ename,salary from t_employee;
-- 如果薪资 >=15000 高工资  一般工资
select ename ,salary , IF(salary>=150000,"高工资","一半工资") from t_employee;
/*
ifnull(value1,value2)
	如果value1 不是null 返回value1

	如果value1 是null 返回默认值value2
*/
-- 获取年薪  保留两位小数
select ename , salary "月薪", TRUNCATE((salary * 12 *(IFNULL(commission_pct,0) + 1)),2)"年薪" from t_employee;
select ename , salary "月薪", ROUND((salary * 12 *(IFNULL(commission_pct,0) + 1)),2)"年薪" from t_employee;
/*
case when 条件 1 then result1
	when 条件 2 then result2
	else result3  end

*/

/*
判断薪资等级
     >20000          A
     15000 <= 20000  B
     10000 <=15000   C
     <10000          D


*/

select 
	ename , salary , 
case 
	when salary > 20000 then "A"
	when salary <= 20000 then "B"
	when salary <= 15000 then "C"
	else "D" end "工资等级"
from  	
	t_employee;
/*
根据入职日期 判断员工的 资深程度   2013 之前入职  老油条

                                   2013-2015      中油条
                                   
                                   2015 之后       小油条
*/

select 
	ename , hiredate ,
case 
	when hiredate < '2013-1-1' then "老油条"
	when hiredate >= '2013-1-1' && hiredate < '2015-1-1' then "中油条"
	else 
		"小油条"
		end "员工资历"
from t_employee;

/*
case expr when 常量值1 then 值1
		when 常量值2 then 值2

*/
-- 展现 每一个员工的部门名称
select * from t_department;

select 
	ename , did ,
case 	did 
when
	1 then "教学部"
when 	
	2 then "咨询部"
else	
	"无业部"
end 	"没有此部门"
from 	
	t_employee;

(六):多行分组函数

avg() 求平均数
sum() 求总和
max() 求最大值
min() 求最小值
count() 求数量

注意:
    1. 把多条记录 汇总为一条结果
    2. 会自动忽略null值
    3. 运行的效率(终止主键运行的效率是最高的,因为主键有索引)
        count(主键)>count(*)>count(3)
        count(主键)>count(1)>count(*)

/*
6.多行(分组)函数
 

*/


select MAX(salary),SUM(salary),AVG(salary),MIN(salary),COUNT(salary)from t_employee;
-- 单行函数与多行函数嵌套
select AVG(salary),ROUND(AVG(salary),2),TRUNCATE(AVG(salary),2) from t_employee;
-- 多行(分组)函数   会自动忽略null值  
select ename, commission_pct from t_employee where commission_pct is not null;
select COUNT(eid),COUNT(*),COUNT(1) from t_employee;
show create table t_employee;

(七):关联查询

关联查询: 去除笛卡尔积 找到符合要求的结果
7.关联查询
    sql标准
   sql92
    会将连接条件和筛选条件放到一起
   sql99
    将连接条件和筛选条件分开
7.1 内连接 
    sql99
    select  展示的字段
    
    from  A [inner] join B
    
    on  连接条件
    
    where 筛选条件;
     
sql92
   
       select  展示的字段
       
       from A,B
       
       where 连接条件 ,筛选条件;
7.2 外连接 

    左外连接
         left join
    右外连接
         right join
    
    全外连接 
        union 将两个结果集并到一起
注意 因为mysql中没有关键字支持全外连接,因此在使用左外连接 和 右外连接的时候,
    字段名以及其顺序要相同

  

select * from t_employee;
select * from t_department;
-- 查询 e.`eid` , e.ename , e.`did` ,d.dname
-- sql99
select e.`eid` , e.ename , e.`did` ,d.dname

from t_employee e inner join t_department d

on 
	e.`did` = d.`did`

-- sql92
select 
	e.`eid` , e.ename , e.`did` ,d.dname

from 
	t_employee e , t_department d
where 
	e.`did` = d.`did`;
	
	
-- 展现 每一个员工的 部门名称
-- sql 99
select	e.`ename` , e.`did` , d.`dname`
	
from 	
	t_employee e inner join t_department d

on
	e.`did` = d.`did`
	
-- sql 92
select	
	e.`ename` , e.`did` , d.`dname`
from 	
	t_employee e , t_department d
where 
	e.`did` = d.`did`;
	
-- -- 展现 每一个员工的 工作名称
-- sql 99
select e.`eid` , e.`ename` , j.`job_id` ,j.`job_name`

from 	
	t_employee e join t_job j
on
	e.`eid` = j.`job_id`;

-- sql 92

select e.`eid` , e.`ename` , j.`job_id` ,j.`job_name`

from t_employee e, t_job j

where 
	e.`eid` = j.`job_id`;
	

	
-- 展现 每一个员工的 部门名称 男员工 并且 薪资 >10000
-- sql 99
select  e.`ename`,e.`salary`,e.`gender`,d.`dname`,d.`description` 
 
from 
	t_employee e join t_department d
on
	e.`did` = d.`did`
where 
	e.`gender` = '男' and e.`salary` > 10000;
	
-- sql 92 

select  e.`ename`,e.`salary`,e.`gender`,d.`dname`,d.`description` 

from 
	t_employee e , t_department d
where	
	e.`did` = d.`did` and e.`gender` = '男' and e.`salary` > 10000;

(八): 全外连接 关联查询的练习 union

1. 将 姚笛的 部门编号设为null

2.将陈赫的 工作编号设为null

3. 在部门表新增一个部门 人事部

4. 在工作表新增一个工作 人事主管


员工表 作为 A 表  部门表 作为B表 
  
展现 A 中 所有的数据  B 中所有的数据     A∪B

员工表 作为 A 表  工作表 作为B表 

展现 A 中 所有的数据  B 中所有的数据     A∪B

 左外连接 展现的是左表所有的数据,右表中没有的话补null

右外连接 展现的是右表所有的数据,左表中没有的话补null

全外连接 展现的是左右表中所有的数据  左表独有的单独占一行 ,右表补null

右表独有的单独占一行 ,左表补null

select e.`ename`,e.`job_id`,j.`job_name`,j.`description`

from t_employee e left join t_job  j

on e.`job_id`=j.`job_id`

union

select e.`ename`,e.`job_id`,j.`job_name`,j.`description`

from t_employee e right join t_job  j

on e.`job_id`=j.`job_id`;

 列出 薪资>9000的 每一个员工的名字  工作名称 工作的描述  部门名称  部门描述

-- sql99

select e.`ename`,e.`salary`,j.`job_name`,j.`description`,d.`dname`,d.`description`

from t_employee e 

join t_job j on e.`job_id`=j.`job_id`

join t_department d  on e.`did`=d.`did`

where e.`salary`>9000;

-- sql92

select e.`ename`,e.`salary`,j.`job_name`,j.`description`,d.`dname`,d.`description`

from t_employee e,t_job j,t_department d 

where e.`job_id`=j.`job_id` and e.`did`=d.`did` and e.`salary`> 9000;

(九):自连接

-- 获取 每一个员工的 员工编号 名字 薪水  上级编号  以及上级员工的 员工编号 名字 薪水  入职日期

-- 当前员工的上级编号 = 上级员工的员工编号

-- 解题思路把当前表即作为员工表又作为上级表

-- 关键是  员工表中的上级id 等于 上级表中的员工id

-- sql 99
select 
	e.`eid` , e.`ename` , e.`salary` , e.`mid` , boss.`eid` , boss.`ename` , boss.`salary` , boss.`hiredate`

from 
	t_employee e join t_employee boss

on	
	e.`mid` = boss.`eid`;
	
-- sql 92
select 
	e.`eid` , e.`ename` , e.`salary` , e.`mid` , boss.`eid` , boss.`ename` , boss.`salary` , boss.`hiredate`
from 
	t_employee e, t_employee boss
where 
	e.`mid` = boss.`eid`

(十) : select 七大子句上

1> from: 从哪些表中筛选

2> on: 关联多表查询时,去除笛卡尔积

3> where : 从表中筛选的条件

4> group by :分组依据

5> having :  在统计结果中再次筛选

6> order by : 排序

7> limit : 分页

select  ename from t_employee where salary >10000;
-- distinct 去重
select distinct did from t_employee;
-- distinct 字段1 字段2  只去除字段1 2 的组合重复情况
select distinct did , job_id from t_employee;
select 
	e.`ename` , d.`dname` , d.`description` , e.`salary` , e.`gender`
from 
	t_employee e , t_department d
where 
	e.`did` = d.`did` and e.`salary` > 10000 and e.`gender` = '女'

 (十一) : select 七大子句中

注意:
    1.group by 进行分组 
      group by 分组的条件;
      
        2. 在进行分组时  select 后面放分组字段 放其他字段有结果 没意义
        (因为分组结束之后总数居的条数将减少,此时如果放其他字段的话,会发生数据与原数据错乱不吻合)

-- 统计 每一个部门的平均薪水
select e.`ename` , e.`did` , AVG(salary) "平均工资"
	
from t_employee e 

group by e.`did`


        
      3.如果对分组后的数据再次筛选 使用having 子句
        
        4.如果分组完毕 就已经拿到了所有的分组结果 可以根据自己的实际需求进行数据展示,
        没有展示出来的数据,也是已经分组后的
        
        5.可以按照多个条件进行分组  

-- 统计 每一个部门的最高薪水
select e.`did` , MAX(e.`salary`)

from t_employee e

group by e.`did`;


select salary from t_employee e where did = 1 order by salary desc limit 1;


-- 统计 男女员工的人数
select e.`gender` , COUNT(e.`eid`) "男女员工人数"

from t_employee e 

group by e.`gender`


-- 统计每一个工作的平均薪水

select e.`job_id` , AVG(e.salary)

from t_employee e

group by e.`job_id`

-- 统计 每一个部门的男生 平均薪水

select e.`did`,e.`ename` , AVG(e.`salary`)

from t_employee e

where e.`gender` = '男'

group by e.`did`

-- 统计 每一个部门的男生 平均薪水 显示 平均薪资>30000
select	e.`ename` , AVG(e.`salary`)

from t_employee e

where e.`gender` = '男'  # 部门中的男生

group by e.`did`   # 根据部门分组分组

having AVG(e.`salary`) > 30000    # having用在分组之后


--  统计 每一个部门的 平均薪水   该部门的人数>=2

select e.`did` , AVG(e.`salary`) , COUNT(1)

from t_employee e

group by e.`did`

having COUNT(e.`eid`) >3 

-- 显示每一个部门的最高薪水 及其部门名称
select e.`did` , MAX(e.`salary`) , d.dname
	
from 	t_employee e join t_department d

on  
	e.`did` =  d.did

group by e.`did`


-- 进行多个条件分组

select e.`did`, e.`job_id` ,AVG(e.`salary`)

from t_employee e

group by e.`did` , e.`job_id`;  # 只有多个条件都相同的才会被分成一组

(十二) : 子查询

where 

    注意:    
         如果子查询的结果数量>1 应该使用 all any 对结果进行修饰
         all 是与子查询所有结果比较
         any 是与子查询任意一个结果比较
         
from 
    将子查询作为数据源
    
    
exists 
    去除没有关联的数据

-- 薪资最高的人的信息

-- 先找到薪资最高是多少
select * 
from t_employee
where salary =
(
	select MAX(salary) from t_employee
);
-- 薪资比 孙红雷  黄晓明  贾乃亮 工资高的人的信息
select * 

from t_employee e

where salary > all

(select salary

from   t_employee e

where e.`ename` in ('孙红雷','黄晓明','贾乃亮'))
-- all  与 In 
select * 

from t_employee e

where salary > any

(select salary

from   t_employee e

where e.`ename` in ('孙红雷','黄晓明','贾乃亮'))

-- 求每一个部门的平均薪水 部门的名称 

select e.did , AVG(e.`salary`),d.dname

from t_employee e , t_department d

where e.`did` = d.did

group by e.`did`;

-- 子查询
-- 求每一个部门的平均薪水 部门的名称 
select e.`did` , AVG(e.`salary`) , d.dname

from t_employee e

group by e.`did`

join 

(select *

from t_department) d

on e.`did` = d.did;
 -- 求每一个部门的平均薪水 部门的名称 
select 	d.`did` , d.`dname` , d.`description` ,e.avgsal

from t_department d

join
(
select `did` ,AVG(salary) avgsal

from t_employee 

group by t_employee.`did`

) e

on d.`did` = e.did ;
 -- 找 有员工的部门 exists
select d.`did` , d.`dname`

from t_department d

where exists

(
select *

from t_employee  e

where 
	e.`did` = d.`did`
)

(十三) : select七大子句 下

注意:
    1.group by 进行分组 
      group by 分组的条件;
      
        2. 在进行分组时  select 后面放分组字段 放其他字段 有结果 没意义
        
        3.如果对分组后的数据再次筛选 使用having 子句
        
        4.如果分组完毕 就已经拿到了所有的分组结果 可以根据自己的实际需求进行数据展示
        
        5.可以按照多个条件进行分组  
            
            
          order by :排序
              排序字段   asc : 从小到大
                         desc: 从大到小
                         
                如果安装多个字段排序: order by 字段1 , 字段2 ,字段3
                
          limit: 分页
          
          limit:(pageNo-1)*pageSize,pageSize;
          
            pageNo:第几页
            pageSize: 每页显示的数量

select ename , salary , did from t_employee order by did asc 

select ename , salary,did  from t_employee order by salary desc;


-- 首先按照 did 从小到大 然后当did 相等 再按照薪水 从大到小
select *
from t_employee e
order by e.`did` ,
salary asc ;

-- 每页显示3条 显示第二页
select * from t_employee
limit 3,3
-- 求 员工的工资>8000 按照部门分组 求平均工资 
select AVG(salary),COUNT(eid),AVG(salary)
from t_employee
where salary > 8000
group by did
having COUNT(eid) >= 4
order by AVG(salary)
-- 显示部门人数>=2 的 结果 按照 最平均工资 排序 
limit 2,2

















(十四) : 事务  (保证了数据的安全性)

保证所有事务都作为一个工作单元来执行,即使出现了故障,都不能改变这种执行方式。当在一个事务中执行多个操作时,要么所有的事务都被提交(commit),那么这些修改就永久地保存下来;要么数据库管理系统将放弃所作的所有修改,整个事务回滚(rollback)到最初状态。

实例

例如转账操作:A账户要转账给B账户,那么A账户上减少的钱数和B账户上增加的钱数必须一致,也就是说A账户的转出操作和B账户的转入操作要么全部执行,要么全不执行;如果其中一个操作出现异常而没有执行的话,就会导致账户A和账户B的转入转出金额不一致的情况,为而事实上这种情况是不允许发生的,所以为了防止这种情况的发生,需要使用事务处理。

事务的ACID属性:

1>原子性(Atomicity)

2>一致性(Consistency)

3>隔离性(Isolation)

4>持久性(Durability)

开启事务(作用效果  使得当前会话永久有效)
    set autocommit = false; 
    
    start transaction;只有一次有效
    
    rollback 回滚
        
    commit     提交
    如果进行一次回滚,或者进行了一次提交代表着当次事务的结束
注意:事务只对  增 删 改 有效

对  DDL 无效

create table account(

	id int primary key auto_increment,
	
	aname varchar(20) ,

	balance int 

)

desc account ;

 -- 开启事务
start transaction ;

-- 事务一直有效
set autocommit = false;


insert into account values(null,"张三",2000);

insert into account values(null,"李四",2000);

select * from account;

update account set balance = 2000  where id = 1;

update account set balance = balance - 1000  where id = 1;

update account set balance = balance + 1000 what id = 2;

rollback;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值