MySQL练习与小结

当你专注一件事的时候,时间总是过得很快!

  • foreign key 练习
-- 切换数据库
use stumgr
-- 删除班级表
drop table t_class1
-- 创建一个班级表
create table t_class1 (
    cno int auto_increment not null,
    cname varchar (12) not null,
    room int (4),
    primary key (cno)
);
-- 查看班级表
desc t_class1
-- 添加班级数据
insert into t_class1 values (null,'Javay1班',501),(null,'Javay2班',502),(null,'大数据1班',401);
-- 查看班级表信息
select * from t_class1
-- 清空班级表数据
truncate table t_class1
-- 删除学生表
drop table t_student1
-- 创建学生表
create table t_student1 (
    sno int primary key auto_increment,
    name varchar (20),
    sex char (1) default '',
    age int,
    classno int,
    constraint fk_t_student1_classno foreign key (classno) references t_class1 (cno)
);
-- 查看学生表
desc t_student1
-- 添加学生表数据
insert into t_student1 values (null,'张三','',22,1);
insert into t_student1 values (null,'李思','',23,3);
insert into t_student1 values (null,'王武','',22,3);
insert into t_student1 (name,age,classno) values ('赵六',21,2),('孙琦',21,1);
-- 查看学生表数据
select * from t_student1
-- 清空学生表数据
truncate t_student1
  • 单行函数练习
-- 单行函数
select * from emp
select lower(ename) from emp
select upper(ename) from emp
select ename from emp
select ename,lower(ename) from emp 
select ename,lower(ename),upper(ename) from emp
select ename,lower(upper(ename)) from emp
-- 使用函数并没有更改数据库中的数据值,只是简化了查询的代码量
select sal from emp
select min(sal),max(sal),sum(sal),avg(sal),count(sal) from emp
-- 函数的分类
-- 单行函数 即对(多行)每一条记录进行操作,分别产生一条记录
-- lower(ename)、upper(name)
-- 多行函数 对(多行)每一条记录进行操作,结果只产生一条记录
-- max(sal)、min(sal)、sum(sal)、avg(sal)、count(sal)
-- 区分单行函数和多行函数
-- 方法1、按照定义区分
-- 方法2、除了多行函数(常用的有5个),都是单行函数
-- 字符函数
select * from emp where length(ename) = 6
select ename from emp where length(ename) = 6
select ename,sal from emp where length(ename) = 6
select ename,lower(ename),upper(ename) from emp 
select empno,ename,job,substring(ename,1,3) subname from emp -- 截取字符串 从第一位到第三位 显示职员信息(工号,姓名,岗位)
select empno,ename,job,replace(job,"CLERK",'店员') from emp where job = 'clerk'
select empno,ename,job,replace(job,'MANAGER','经理') from emp where job = "MANAGER"
select job from emp where job = 'manager'
-- select job where job = 'manager' from emp -- 错误的写法
select empno,ename,job,replace(job,"MANAGER","经理") from emp where job = 'manager'
select empno,ename,job,replace(job,'manager',"经理") from emp where job = "MANAGER" -- replace()括号中的职位名必须和表格中一样,不然显示不出后面的汉字
-- 数值函数
select 
abs(-5), -- 取绝对值
ceil(3.2), -- 向上取整
floor(3.2), -- 向下取整
round(3.4),
round(3.5), -- 四舍五入
mod(10,3),
mod(10,5), -- 取模 相当于取余
pi(), -- 圆周率
sqrt(25), -- 开平方
pow(2,5),
pow(5,2) -- 幂运算
select rand(),rand(),rand() -- 返回0~1之间的随机数
select truncate(3.1415926,3) -- truncate(num,n)返回num舍弃小数点后第n位后的数值
-- 日期函数
select now(),sysdate(),sleep(3),sysdate(),now()
select now(),curdate(),curtime()
-- 流程函数
select ename,deptno,sal,if(sal >= 3000,"high","low") from emp 
select ename,deptno,sal,if(sal >= 3000,'高收入层','低收入层') from emp order by sal 
select ename,deptno,job,sal*12+comm year_income from emp -- 算上补贴的年收入,补贴(comm)为null无法算出年收入
select ename,deptno,job,sal*12+ifnull(comm,0) year_income from emp -- 加上ifnull(comm,0)可以把补贴为null的置为0,从而得出年收入
-- ifnull(comm,0) 即 if comm is null then comm = 0
select nullif(1,1),nullif(1,2),nullif(2,1),nullif(2,2) -- if 1 == 2 then null else 1
select ename,deptno,sal,case when sal >= 3000 then '高收入' else "低收入" end sal_level from emp 
select ename,deptno,sal,
case when sal >= 3000
then 'high'
else case when sal >= 2000
then 'mid'
else 'low'
end
end
from emp
-- 其他函数
select database(),user(),version(),password('zhangsan'),inet_aton('192.168.10.1'),inet_ntoa(3232238081)
-- mysql 提供了一个名为dual的虚拟表 默认的from dual是可以省略的
  • 单表查询练习
-- where 子句练习
select * from emp -- 先查看下员工表信息
select * from emp where empno = 7566 -- 查询工号为7566的职员信息
select * from emp where sal > 3000 -- 查看薪水大于3000的职员信息
select * from emp where job = 'MANAGER'
select * from emp where JOB = 'manager' -- mysql 中默认不去分大小写
-- 加上区分大小写的条件 即在查询的字段名前加上binary
select * from emp where binary job = 'manager'
select * from emp where job != 'manager'
select * from emp where job > 'manager' -- 字符串也可以大于小于
select * from emp where job <> "manager"
select * from emp where hiredate < '1981-12-23'
-- and 逻辑运算符
select * from emp 
select * from emp where sal <= 3000 and sal >= 1200
select * from emp where sal between 1200 and 3000 -- between 表示的意思是闭区间
select * from emp where sal not between 3000 and 1200
select * from emp where sal <= 3000 && sal >= 1200 -- &&等同于and
-- or 逻辑运算符
select * from emp where deptno = 30 or 10 -- 不能这样表述
select * from emp where deptno = 30 or deptno = 10 -- 查询部门编号为30或10的
select * from emp where deptno = 30 || deptno = 10 -- ||等同于or
select * from emp where deptno in (30,10)
select * from emp where deptno in (10,30)
-- 模糊匹配
-- 姓名中带K的 %代表任意多个字符
select * from emp 
select * from emp where ename = '%K%' -- 不能使用等号 而是要用单词 like
select * from emp where ename like '%k%' -- K 不区分大小写
-- 加上binary就是区分大小写
select * from emp where binary ename like '%K%'
select * from emp where binary ename like '%k%'
select * from emp where binary ename not like '%k%'
select * from emp where binary ename not like '%K%'
-- 姓名的第二个字母是L _单个下划线代表任意一个字符 第几个字符要加几个_
select * from emp where ename like '__m%' -- 名字中第二个字母是m的职员信息
select * from emp where ename like '_M%' -- 名字中第一个字母是m的职员信息
select * from emp where binary ename like '_m%' -- 区分大小写 名字中第一字母是小写m的职员信息
select * from emp where binary ename like '_M%' -- 名字中第一个字母是大写M的职员信息
-- is null
select * from emp where comm = 0 -- 不是is null的用法
select * from emp where comm is null -- 查看comm是null的职员信息,comm是null和comm = 0 代表的含义是不同的
select * from emp where comm is not null -- is 后加 not 是正确的用法 not加在is前不符合语法要求
-- select * from emp where comm not is null
select * from emp where comm != 0 -- 不包括comm为null的数据
-- 小括号 优先级高
select * from emp where job = 'salesman' or "CLERK" and sal >= 1280 -- and运算符的优先级比or高 不包括工资大于1280的clerk
select * from emp where (job = "salesman" or job = "clerk") and sal >= 1280
select * from emp where job = 'SALESMAN' or (job = 'CLERK' and sal >1280)
  • 表单查询多行函数
-- 多行函数
select max(sal),min(sal),sum(sal),count(sal),avg(sal) from emp
select
max(comm),min(comm),sum(comm),avg(comm),count(comm) 
from emp
select * from emp 
select 
max(ename),min(ename),sum(ename),avg(ename),count(ename) 
from emp
-- 统计有几个员工
select
empno,count(1)
from emp
select count(comm) from emp -- 不能通过领补贴的人来统计
-- 统计有几个部门
select deptno from dept
select count(distinct deptno) from emp -- 部门40并未出现在emp表中,所以此语句输出的部门个数是3
select count(deptno) from dept
-- 对任意一张表,统计有几条记录
select count(*) from emp
select count(*) from dept
select empno from emp -- 可以通过主键统计
select 1 from emp
select count(1) from emp -- 统计表的记录个数建议用此方法,比count(*)效率高
-- 统计有几个岗位
select count(distinct job) from emp
-- 多行函数会自动排除null值
-- max(),min(),count()适用于所有数据类型
-- sum()avg()仅限于数值类型(整点 浮点)
-- 多行函数会更多地用在分组查询中 group by
  • 多表查询练习
-- SQL99多表连接查询
-- 查询员工的编号、姓名和部门编号
select * from emp
select empno,ename,deptno from emp
-- 查询员工的编号、姓名和部门编号、部门的名称
-- 交叉连接 使用关键字join
select * from dept
select * from emp
select *
from emp
cross join dept
select *
from dept
cross join emp -- 左和右的区别 左连接 右连接
-- 自然连接
select *
from emp
natural join dept
-- 使用关键字natural 会自动按照所有的同名列进行匹配,并且同名列只显示一次
-- 优点是:简单
select empno,ename,deptno,dname
from emp
natural join dept
-- 缺点:没有指定各字段属于哪个表,执行时需要进行判断,效率低
-- 解决:给各个字段指定表的名字
select emp.empno,emp.ename,deptno,dept.dname -- 自然连接中同名列不能使用表名前缀
from emp 
natural join dept
-- 缺点:表名如果很长,字段多的时候,SQL语句就会显得复杂
-- 解决:使用别名
select e.empno,e.ename,deptno,d.dname
from emp e
natural join dept d
-- using 子句
-- 自然连接的缺点:会自动按照“所有的”同名列进行匹配,如果希望按照某一个同名列进行匹配,自然连接无能为力
-- 解决:使用using子句
select * 
from emp e
join dept d
using(deptno) -- e.deptno = d.deptno
select e.empno,e.ename,deptno,d.dname
from emp e
join dept d
using(deptno)
-- on子句
-- natural、using的缺点:都必须有同名列
-- 连接查询要求两个表必须由关联(比如emp的deptno和dept的deptno),但是不要同名
-- 如果有关联,但是不同名,该怎么解决?
select empno,ename,d.deptno,d.dname -- 关联列必须使用前缀
from emp e
join dept d
on(e.deptno = d.deptno) -- 此处e和d的deptno碰巧同名了
-- 查询员工的编号、姓名、部门编号、部门的名称,要求薪水大于2000
select empno,ename,d.deptno,d.dname
from emp e
join dept d
on(e.deptno = d.deptno)
where sal > 2000
-- 小结:
-- 实际开发中尽量使用on子句,不管是否有同名列,都可以使用;虽然稍显复杂,但是可读性高
-- SQL99连接查询的优点:连接条件和筛选条件是分开的
-- 连接条件:on(e.deptno = d.deptno) using(deptno) natural cross
-- 筛选条件:where sal > 2000
-- SQL92中,连接条件和筛选条件是没有分开的
  • 外连接查询
-- SQL99外连接查询
select * from dept
select * from emp
update emp set deptno = null where empno = 7788; -- 把scott员工设置成没有部门
select *
from emp e
join dept d
on(e.deptno = d.deptno) -- 返回13条记录,缺少了没有部门的员工scott,缺少了没有员工的部门40;只显示匹配的数据
-- 左外连接
select *
from emp e
left join dept d
on(e.deptno = d.deptno)
-- 右外连接
select *
from emp e
right join dept d
on(e.deptno = d.deptno)
-- 全外连接
select *
from emp e
full join dept d
on(e.deptno = d.deptno) -- mysql中没有全外连接
-- 曲线救国
select *
from emp e
left join dept d
on(e.deptno = d.deptno)
union -- 使用union关键字可以曲线实现全外连接
select *
from emp e
right join dept d
on(e.deptno = d.deptno)
  • group by having练习
-- 统计各部门的平均工资(只显示平均工资2000以上的)
select deptno,avg(sal)
from emp
group by deptno
having avg(sal) > 2000
order by avg(sal)
select avg(sal) from emp -- 这是所有部门的平均工资
select deptno from emp
select deptno,avg(sal) from emp -- 字段不能和分组函数共存,除非该字段是分组group by字段
select deptno,avg(sal)
from emp
group by deptno
select deptno,avg(sal)
from emp
-- where avg(sal) > 2000 -- where 子句不能使用多行函数(分组函数)
group by deptno
having avg(sal) >2000 -- 各个子句的书写是有顺序的
order by avg(sal) desc
-- 统计各个岗位的平均工资,除了manager
select distinct job from emp
select job,avg(sal)
from emp
group by job 
having job != 'MANAGER'
order by avg(sal)
select job,avg(sal)
from emp
group by job 
having job != 'MANAGER' && job != 'PRESIDENT'
order by avg(sal)
-- where 子句不能使用多行函数(分组函数)
select job,avg(sal),count(1)
from emp
where count(1) > 3
group by JOB
-- 如果没有group by子句,select列表中不允许出现字段(单行函数)与多行函数混用的情况
-- 出现在select列表中的字段,如果不是包含在多行函数中,那么该字段必须同时在group by子句中出现
-- 不允许在where子句中使用多行函数
-- 小结
-- where子句和having子句的联系和区别
-- 联系
-- 都是筛选记录
-- 区别
-- ◆where是group by之前,having是group by之后
-- ◆where中不能出现在多行函数,having中可以出现多行函数
-- select语句总结
-- ◆select语法格式
-- ◆select column,group_function(column)
-- ◆from table
-- ◆[where condition]
-- ◆[group by group_by_expression]
-- ◆[having group_condition]
-- ◆[order by column]
-- ◆select语句执行顺序
-- ◆from--->where--->group by--->select-having--->order by
  • group by having加强练习
-- 列出工资最小值小于2000的职位
select job,min(sal)
from emp
group by job 
having min(sal) < 2000
order by min(sal)
-- 获取各个职位的最小工资
select job,min(sal)
from emp
group by job
having min(sal)
order by min(sal) desc -- 按最小工资降序排列
-- 获取各个职位的最小工资,筛选出小于2000的
select job,min(sal)
from emp
group by job
having min(sal) < 2000
-- 列出平局工资大于1200元的部门和工作搭配组合
select * from emp
select * from dept
select distinct deptno from emp 
select distinct job from emp 
select distinct job,deptno from emp
select deptno,job,avg(sal),count(1)
from emp 
group by deptno,job
having avg(sal) > 1200
order by avg(sal) desc
-- 统计人数小于4的部门的平均工资
select deptno,avg(sal),count(1)
from emp 
group by deptno
having count(1) < 4
-- 统计各部门的最高工资,排除最高工资小于3000的部门
select deptno,max(sal)
from emp
group by deptno
having max(sal) >= 3000
order by max(sal) 

一休哥~~~

posted @ 2019-11-26 22:32  我有两个皮夹克  阅读(201)  评论(0编辑  收藏  举报