MySQL 查询题型总结

### MySQL 3
use `school`;-- 查询所有学生的所有信息
select * from tb_student;
select  stu_id,stu_name,stu_addrfrom tb_student;use school;
-- 查询学生的学号、姓名和籍贯(投影)
select stu_id as 学号,stu_name as 姓名,stu_addr as 籍贯 from tb_student;
-- alias _ 别名
-- 查询所有课程的名称及学分(投影和别名)
select stu_id as '学生编号',stu_name as '学生姓名'from tb_student;  -- 查询所有女学生的姓名和出生日期(筛选)
select stu_name,stu_birthfrom tb_studentwhere stu_sex = 0;-- 查询籍贯为“四川成都”的女学生的姓名和出生日期(筛选)
select stu_name,stu_birthfrom tb_studentwhere stu_sex = 0 andstu_addr = '四川成都';-- 查询籍贯为“四川成都”或者性别是女的学生
select stu_name,stu_birthfrom tb_studentwhere stu_sex = 0 orstu_addr = '四川成都';-- 查询所有80后学生的姓名、性别和出生日期(筛选)
select stu_name,stu_sex,stu_birthfrom tb_studentwhere stu_birth>='1980-1-1' andstu_birth<='1990-1-1';
-- 或者使用betwee    and
-- 可以做数学运算,性别+10,还可以做除法运算,加法,求余数,加减乘除求余运算,写筛选条件也可以写数学运算
select stu_name,stu_sex +10,stu_birthfrom tb_studentwhere stu_birth between '1980-1-1' and '1990-1-1';-- 查询学分大于2的课程的名称和学分(筛选)
select cou_name as '课程名称',cou_credit as '课程学分'from tb_coursewhere cou_credit > 2;-- 查询学分是奇数的课程的名称和学分(筛选)
select cou_name ,cou_credit from tb_coursewhere cou_credit mod 2 <> 0;       -- 这两种方法都可以的-- where cou_credit % 2 <> 0 ;    -- mod 取余-- 查询选择选了1111的课程考试成绩在90分以上的学生学号(筛选)
select stu_idfrom  tb_recordwhere cou_id = 1111 andscore > 90;-- 查询名字叫“杨过”的学生的姓名和性别
select stu_name as '学生姓名',
-- case when then else end 分支结构
-- 使用if函数构造分支结构, if 是mysql方言,不建议使用,不适用于其他的数据库--  if(stu_sex ,'男','女') as 性别case stu_sex  when 1 then '男' when 0 then '女' else '未知' end  as '学生性别'  from tb_studentwhere stu_name = '杨过';--  ¥¥¥ 复习的时候,练习写的
select stu_name as '学生性别',case stu_sex when 1 then '男' when 0 then '女' else '未知' end as '性别'from tb_studentwhere stu_name = '杨过';-- 查询姓“杨”的学生姓名和性别(模糊)
-- like是像的意思
-- 通配符 - wild card - 百搭牌
-- % 匹配0个或任意多个字符
-- _ 下划线精确匹配一个字符,如果要匹配两个字符,就写两个下划线
-- 方法1 使用 _ 来匹配,一个_匹配一个字符,两个_ _ 匹配两个字符
select stu_name,stu_sexfrom tb_student-- where stu_name like '杨%'; where stu_name like '杨_' orstu_name like '杨__';   -- 两种方法都可以
-- 方法2 使用%来匹配
select stu_name,case stu_sex when 1 then '男' when 0 then '女' else '未知' end  as '性别'from tb_studentwhere stu_name like '杨%';-- 查询姓“杨”名字两个字的学生姓名和性别(模糊)
select stu_name,stu_sexfrom tb_studentwhere stu_name like '杨_';-- 查询姓“杨”名字三个字的学生姓名和性别(模糊)
select stu_name,stu_sexfrom tb_studentwhere stu_name like '杨__';-- 查询名字中有“不”字或“嫣”字的学生的姓名(模糊)
select stu_name,stu_sexfrom tb_studentwhere stu_name like '%不%' orstu_name like '%嫣%';-- 方法2使用union 连接两个查询,把两个条件分开写。
select stu_name,stu_sexfrom tb_studentwhere stu_name like '%不%'
union  -- union all是把集合的元素不去重,直接把数据组装起来,而union 是会去重的,
select stu_name,stu_sexfrom tb_studentwhere stu_name like '%嫣%';-- 关系代数-以集合论、一阶谓词逻辑逻辑-- mysql没有交,差运算,只有并集运算。-- 使用正则表达式进行查询,在必知必会第9章。-- 查询姓“杨”名字三个字的学生姓名和性别(模糊)-- regexp  -  regular expression - 正则表达式select  stu_namefrom tb_studentwhere stu_name regexp '[杨][\\u4e00-\\u9fa5]{1,2}';  # -- \表示转义,\u表示的是unicode编码。-- 查询姓“杨”或姓“林”名字三个字的学生的姓名(正则表达式模糊查询)
select  stu_namefrom tb_studentwhere stu_name regexp '[杨林][\\u4e00-\\u9fa5]{2}';
-- 查询没有录入籍贯的学生姓名(空值处理)
-- 三值逻辑: true / false / unkown   <-----空值做任何运算的结果,结果仍然是空值,空值做关系运算,逻辑运算,会产生unkown,判断空或者非空,要写is null ,或者is not null。
-- 为空要写 is null ,不为空,写is not null
-- tirm --MYSQL函数- 修剪字符串两端的空格.
select stu_namefrom tb_studentwhere stu_addr is null ;  -- sql关系运算,真假未知,update  tb_student set stu_addr  = '' where stu_id = 3755;
-- 查询录入了籍贯的学生姓名(空值处理)
select stu_namefrom tb_studentwhere stu_addr is not  null ;
-- 如果字符串是空字符串
-- 下面查询没有籍贯的学生,包括字符串的值为空
select stu_namefrom tb_studentwhere stu_addr is null or stu_addr = '';   #可以查到两个学生记录-- 下面查询有籍贯的学生,不包括字符串的值为空
select stu_namefrom tb_studentwhere stu_addr is  not null andstu_addr <> '';
-- 如果查询的数据中,字符串是很多空格,以上方法任然查不出来。,要加函数trim(),如果要去掉左边的空格或数据,就使用leleading'什么内容'
-- 德摩根律
update tb_student set stu_addr = '   ' where stu_id = 3755;
-- 找地址空的
select stu_namefrom tb_studentwhere stu_addr is null or trim(stu_addr) = '';
-- 找地址非空
select stu_namefrom tb_studentwhere stu_addr is not null andtrim(stu_addr) <> '';
-- 查询学生选课的所有日期(去重)
-- distinct 去重
select distinct sel_datefrom tb_record;-- 查询学生的籍贯(去重)
select distinct sel_datefrom tb_recordwhere stu_addr is not null andtrim(stu_addr) <>'';
-- 查询男学生的姓名和生日按年龄从大到小排列(排序)
-- asc ascending  -上升 - 从小到大
-- desc -- descending  - 下降 - 从大到小
select stu_name,stu_birthfrom tb_studentwhere stu_sex = 1order by stu_birth asc, stu_id desc;
-- 时间日期函数
-- now() - 获取当前数据库服务器的时间
-- curdate() - current date - 获取当前日期
-- curtime()  --current time - 获取当前时间
-- datediff(dt1,dt2)
-- 数数值函数
-- floor() - 向下取整
--  ceiling() /ceil() - 向上取整
-- round()- 四舍五入
select now();  -- 当前时间日期
select curdate();  -- 当前日期
select curtime();  -- 当前时间
-- 补充:将上面的生日换算成年龄(日期函数、数值函数)
select stu_birth,stu_name,floor(datediff(curdate(),stu_birth)/365) as '年龄'from tb_studentwhere stu_sex = 1 order by 年龄 desc;
help functions;
help time;
-- 查询年龄最大的学生的出生日期(聚合函数) - 查询最小的生日
select min(stu_birth)from tb_student;-- 查询年龄最小的学生的出生日期(聚合函数)  - 查询年龄最小的
select max(stu_birth)from tb_student;
-- 查询编号为1111的课程考试成绩的最高分(聚合函数)
select max(score)from tb_recordwhere cou_id = 1111;   -- 95.0
-- 查询学号为1001的学生考试成绩的最低分(聚合函数)
select min(score)from tb_recordwhere stu_id = 1001;  -- 87.5
-- 查询学号为1001的学生考试成绩的平均分(聚合函数)
-- 注意:聚合函数不会处理空值(null),即求和,计数不会考虑空值的。
-- 聚合函数有max/min/avg/sum/count
-- count(*) 统计所有的行数,count(score)统计所有的非空值
-- coalesce(x,y,z)返回参数中第一个非空值。
select round(avg(score),1)  -- 95.6from tb_recordwhere stu_id = 1001;  -- 95.62500 --想要保留几位小数,使用round函数。-- 查询学号为1001的学生考试成绩的平均分,如果有null值,null值算0分(聚合函数)
select round(avg(score),1)  -- 95.6from tb_recordwhere stu_id = 1001;  -- 95.62500-- 方法1
select sum(score)/count(*) from tb_recordwhere stu_id = 1001;  -- 76.50000
-- 方法2 ifnull --MYSQL函数,如果score是空值,就返回0,否则就是返回score.
select avg(ifnull(score,0)) from tb_recordwhere stu_id = 1001;  -- 76.5
-- 方法3 使用 coalesce
select avg(coalesce(score,0))   -- 通用的from tb_recordwhere stu_id = 1001;   -- 76.50000
-- 方法4
select avg(case when score is null then 0 else score end)from tb_recordwhere stu_id = 1001;  -- 76.5000
-- Hao(jackfrued) 14:09:05
-- 获取描述性统计信息
-- 均值、中位数、分位数、最大值、最小值、极差(全距)、方差、标准差
-- 均值在数据大小比较几种的时候,有很好的代表性
-- 方差 :给误差(每个数据跟均值的差)的平方求平均值。
-- 总体方差:
-- 样本方差:
-- 方差越大,均值的代表性越弱,方差越小,均值的代表性越好。
-- 查询学号为1001的学生考试成绩的标准差(聚合函数)
-- MYSQL函数  - std
-- oracle函数 -  stddev
-- 标准SQL
-- 标准差SQL - stddev_pop / sttdev_samp  总体标准差与样本标准差
-- 标准方差SQL - var_pop / var_samp  总体方差与样本方差
-- population - 总体 / sample - 样本
-- MYSQL方言 - std
--
select variance(score)from tb_recordwhere stu_id = 1001;  -- 方差 26.17select round(stddev(score),2)from tb_recordwhere stu_id = 1001;  -- 标准差 5.12
select round(stddev(score),2)from tb_recordwhere stu_id = 1002;    -- 11.5
-- 举例说明 样本方差和标准差的计算
select stddev_samp(score)from tb_recordwhere stu_id = 1002;   -- 样本标准差16.263455967290593select var_samp(score)from tb_recordwhere stu_id = 1002;   -- 样本方差 264.5select stddev_pop(score)from tb_recordwhere stu_id = 1002;   -- 总体标准差11.5select var_pop(score)from tb_recordwhere stu_id = 1002;   -- 总体方差132.25
help functions;  --查函数
help 'Aggregate Functions and Modifiers';  -- 查聚合函数-- 查询男女学生的人数(分组和聚合函数) - 根据性别统计人数
-- 要学会在不同的维度拆解数据
select case stu_sex when 1 then '男'else '女' end as 性别,count(*) as 人数from tb_studentgroup by stu_sex;-- 查询每个学院学生人数(分组和聚合函数)
select col_id as 学院,
count(*) as 人数from tb_studentgroup by col_id;-- 查询每个学院男女学生人数(分组和聚合函数)
select col_id as 学院编号, -- 别名不需要单引号case stu_sex when 1 then '男' else '女' end as 性别,count(*) as 人数from tb_studentgroup by col_id,stu_sex;
-- 查询每个学生的学号和平均成绩(分组和聚合函数)
select stu_id as 学生学号,round(avg(score),1) as 平均分from tb_recordgroup by stu_id;
-- 听过学号分组,然后计算平均分
-- 查询平均成绩大于等于90分的学生的学号和平均成绩
select stu_id,avg(score) as '平均成绩'from tb_recordgroup by stu_idhaving avg(score) >= 90; -- 查询1111、2222、3333三门课程平均成绩大于等于90分的学生的学号和平均成绩
select stu_id as 学号,cou_id as  课程编号,round(avg(score),1) as 平均成绩from tb_recordwhere cou_id in (1111,2222,3333)group by stu_idhaving avg(score) >= 90;   -- 查询年龄最大的学生的姓名(子查询/嵌套查询)
-- 以前的方法
select min(stu_birth)  -- 赋值不能用等号,等号表示相等,判断的,赋值要用海象运算符from tb_student;  -- 1985-04-17
-- 新的方法
select @x := min(stu_birth)  -- 赋值不能用等号,等号表示相等,判断的,赋值要用海象运算符from tb_student;
select @x ;  -- 把值赋值给了@X
select stu_namefrom tb_studentwhere stu_birth = @x;  -- 杨不悔
-- 方法2 subquery - 把一个查询结果作为另一个查询的一部分来使用!!!
select stu_namefrom tb_studentwhere stu_birth = (select min(stu_birth)  from tb_student);  -- 杨不悔-- 查询选了两门以上的课程的学生姓名(子查询/分组条件/集合运算)
select stu_namefrom tb_studentwhere stu_id in (select stu_id   from tb_record group by stu_idhaving count(*) > 2);-- 学号在这个集合里面就要去把数据拿出来。也可以写成一下方法
-- any 是一个谓词,可以产生真和假 ,作用是只要和后面任意一个匹配上,就返回真。
-- all 是一个谓词,----> 所有的元素都匹配成功才返回true.
-- in 集合运算也称为一个谓词。
-- 自己理解的 any是只要匹配上,就会返回值,然后会把集合里面每一个都元素都进行匹配?
select stu_namefrom tb_studentwhere stu_id = any (select stu_id   from tb_record group by stu_idhaving count(*) > 2);
%*
杨过
王语嫣
项少龙
*%
-- 查询学生的姓名、生日和所在学院名称 (连接/表查询--- 从多张表投影字段)-- from 子句如果放多张表但是没有连接记录的条件就会形成一个笛卡尔积,
-- 通过连接条件可以多张表满足条件的记录连接起来
-- python -- > 包名.模块名.函数名 ---> 完全限定名
-- 列,表都可以别名 as 可以省略-- from  a  import foo
-- from b import foo
-- import a
-- import b
-- a.foo
-- b.foo
select  stu_name,stu_birth,col_name-- from tb_student as t1,tb_college as t2  -- 给两张表换个名字-- where t1.col_id = t2.col_id;from tb_student as t1,tb_college as t2 where tb_student.col_id = tb_college.col_id;-- 或者使用 from 表1 iner join 表名2 on 条件   ;select  stu_name,stu_birth,col_namefrom tb_student inner join tb_college on tb_student.col_id = tb_college.col_id ;-- 查询学生姓名、课程名称以及成绩(连接查询/联结查询)
select stu_name,cou_name,scorefrom tb_student as t1,tb_course as t2,tb_record as t3where t1.stu_id = t3.stu_id andt2.cou_id = t3.cou_id andscore is not null-- 方法2 内连接  使用 inner join  on -- Error Code: 1064. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'nul' at line 5select stu_name,cou_name,scorefrom tb_student inner join tb_record on tb_student.stu_id = tb_record.stu_id inner join tb_course  on tb_course.cou_id = tb_record.cou_idwhere  score is not null ;-- 注意: 写时候on 后面的连接条件的时候,一定要注意对应关系。-- 方法3 自然连接 表1 natural join 表2 ,如果有同名列,就会连接,如果没有同名列,就会产生笛卡尔积。select stu_name,cou_name,scorefrom tb_student natural join tb_course natural join tb_record where  score is not null;-- 补充:上面的查询结果取前5条数据(分页查询)-- limit 数字 只拿前几条
-- offset 数字  --- 跳过指定数字个 ,分页数据select stu_name,cou_name,scorefrom tb_student natural join tb_course natural join tb_record where  score is not nullorder by cou_id asc ,score desclimit 5offset 10; -- limit 数字1,数字2   --- 跳过数字1个数据,拿数字2个数据   。-- 方法2 使用limit 数字1,数字2select stu_name,cou_name,scorefrom tb_student natural join tb_course natural join tb_record where  score is not nullorder by cou_id asc ,score desclimit 10 , 5;-- 补充:上面的查询结果取第6-10条数据(分页查询)
use school;select stu_name,cou_name,scorefrom tb_student natural join tb_course natural join tb_record where  score is not nullorder by cou_id asc ,score desclimit 5 , 5;
-- 补充:上面的查询结果取第11-15条数据(分页查询)select stu_name,cou_name,scorefrom tb_student natural join tb_course natural join tb_record where  score is not nullorder by cou_id asc ,score desclimit 10 , 5;-- 查询选课学生的姓名和平均成绩(子查询和连接查询)
select stu_name ,avg_scorefrom tb_student natural join (select stu_id,round(avg(score),1) as avg_scorefrom tb_recordgroup by stu_id) as tb_ave;
select stu_name as 学生姓名,round(avg(score),1) as 平均成绩from tb_student natural join  tb_recordgroup by stu_id;-- 查询学生的姓名和选课的数量 (只能查到选了课的学生的姓名和数量,还有三个没有选课的学生,不会查到)
-- 方式1 使用两个表的自然连接,是通过学号
select stu_name as 学生姓名,count(*) as 选课数量from tb_student natural join  tb_recordgroup by stu_id;-- 方式2   使用内连接select stu_name as 学生姓名,count as 选课数量from tb_student inner join  select(group by stu_id;-- 查询每个学生的姓名和选课数量(左外连接和子查询)-- 内连接/自然连接:只会将两张表满足连表条件的记录取到
-- 左外连接:获取左表(写在join前面的表)所有的数据,不满足连表条件的地方填充null
-- 写法:left outer join  /left join
-- 右外连接:获取右表(写在join后面的表)所有的数据,不满足连表条件的地方填充null
-- 写法:rignt outer join  /rignt join
-- 全外连接:获取左表和右表所有数据,不满足连表条件的地方填充null (mysql不支持全外连接)
-- 写法:full outer join  /full join
-- 在MYsql中如果要实现全外连接的效果,可以用左外连接和右外连接求并集
select  stu_name,count(rec_id) as 选课数量from tb_student  left outer join tb_record on tb_student.stu_id = tb_record.stu_idgroup by tb_student.stu_id;select stu_name,count(rec_id) as totalfrom tb_student left join (select )-- 查询没有选课的学生的姓名
-- 方法一、去重加集合运算,集合运算 去重操作,性能比较低,
select stu_namefrom tb_studentwhere stu_id not in (select distinct stu_idfrom tb_record);
-- 方法2 按照两个集合的差集方法,两个表进行左连接,然后,右表的主键是空集
select stu_namefrom tb_student left join tb_recordon tb_record.stu_id = tb_student.stu_idwhere  rec_id is null;#### 练习提升题-- 01. 查询课程1111比课程2222成绩高的所有学生的学号
select sid1
from (select stu_id as sid1, score from tb_record where cou_id=1111) as t1
inner join (select stu_id as sid2, score from tb_record where cou_id=2222) as t2
on sid1=sid2
where t1.score>t2.score;-- 02. 查询没有学过张三丰老师的课程的同学的学号和姓名
select stu_id, stu_name
from tb_student
where stu_id not in (select stu_id from tb_teacher natural join tb_course natural join tb_recordwhere tea_name='张三丰'
);select stu_id, stu_name
from tb_student as t1
where not exists (select 'x' from tb_teacher natural join tb_course natural join tb_record as t2where t1.stu_id=t2.stu_id and tea_name='张三丰'
);-- 03. 查询学过课程1111和课程2222的同学的学号和姓名
select stu_id, stu_name
from tb_student
where stu_id in (select t1.stu_id from tb_record t1inner join tb_record t2 on t1.stu_id=t2.stu_idwhere t1.cou_id=1111 and t2.cou_id=2222
);-- 04. 查询所有课程成绩大于80分的同学的学号和姓名
select stu_id, stu_name
from tb_student
where stu_id in (select stu_idfrom tb_recordgroup by stu_idhaving min(score)>80
);-- 05. 查询学习了所有课程的同学的学号和姓名
select stu_id, stu_name
from tb_student
where stu_id in (select stu_id from tb_record group by stu_idhaving count(cou_id)=(select count(cou_id) from tb_course)
);-- 06. 查询至少有一门课跟学号1001同学所学课程相同的同学的学号和姓名
select stu_id, stu_name
from tb_student
where stu_id in (select distinct stu_id from tb_record where cou_id in (select cou_id from tb_record where stu_id=1001) and stu_id<>1001
);-- 07. 查询所学课程与1002同学完全相同的同学的学号和姓名-- 08. 查询有课程不及格(60分以下)的同学的学号和姓名-- 09. 查询每门课程的名称、最高分、最低分和平均分-- 10. 查询每门课程第2名和第3名的学生姓名和对应的成绩-- 11. 查询每门课程各分数段(100-90,90-80,80-70,70-60,60以下)的人数占比
select cou_id,sum(if(score>=90 and score<=100, 1, 0))/count(score) as A,sum(if(score>=80 and score<90, 1, 0))/count(score) as B,sum(if(score>=70 and score<80, 1, 0))/count(score) as C,sum(if(score>=60 and score<70, 1, 0))/count(score) as D,sum(if(score<60, 1, 0))/count(score) as E
from tb_record
group by cou_id;-- 12. 查询本周过生日的学生的姓名和生日(考察对日期函数的熟练程度)
select stu_name, stu_birth
from tb_student
where weekofyear(stu_birth)=weekofyear(curdate());
-- where weekofyear(stu_birth)+1=weekofyear(curdate());  -- 上周过生日
-- where weekofyear(stu_birth)=weekofyear(curdate())+1; -- 下一周过生日-- 补充日期函数中日期格式化---date_format(数据,‘转换的格式’)-- 1.日期格式化函数
-- date_format()-- %a 缩写星期名
-- %b 缩写月名
-- %c 月,数值
-- %D 带有英文前缀的月中的天
-- %d 月的天,数值(00-31)
-- %e 月的天,数值(0-31)
-- %f 微秒
-- %H 小时 (00-23)
-- %h 小时 (01-12)
-- %I 小时 (01-12)
-- %i 分钟,数值(00-59)
-- %j 年的天 (001-366)
-- %k 小时 (0-23)
-- %l 小时 (1-12)
-- %M 月名
-- %m 月,数值(00-12)
-- %p AM 或 PM
-- %r 时间,12-小时(hh:mm:ss AM 或 PM)
-- %S 秒(00-59)
-- %s 秒(00-59)
-- %T 时间, 24-小时 (hh:mm:ss)
-- %U 周 (00-53) 星期日是一周的第一天
-- %u 周 (00-53) 星期一是一周的第一天
-- %V 周 (01-53) 星期日是一周的第一天,与 %X 使用
-- %v 周 (01-53) 星期一是一周的第一天,与 %x 使用
-- %W 星期名
-- %w 周的天 (0=星期日, 6=星期六)
-- %X 年,其中的星期日是周的第一天,4 位,与 %V 使用
-- %x 年,其中的星期一是周的第一天,4 位,与 %v 使用
-- %Y 年,4 位
-- %y 年,2 位SELECT  DATE_FORMAT(day,'%W, %M %e, %Y')  AS day FROM Days;-- 问题 {"headers":{"Days":["day"]},"rows":{"Days":[["2022-04-12"],["2021-08-09"],["2020-06-26"]]}}
-- 结果 {"headers": ["day"], "values": [["Tuesday, April 12, 2022"], ["Monday, August 9, 2021"], ["Friday, June 26, 2020"]]}### MySQL  4  第几前几——---——窗口函数-- 如果存在就删除名为hrs的数据库
drop database if exists `hrs`;-- 创建名为hrs的数据库并指定默认的字符集
create database `hrs` default charset utf8mb4;-- 切换到hrs数据库
use `hrs`;-- 创建部门表
create table `tb_dept`
(
`dno` int not null comment '编号',
`dname` varchar(10) not null comment '名称',
`dloc` varchar(20) not null comment '所在地',
primary key (`dno`)
);-- 插入4个部门
insert into `tb_dept` values (10, '会计部', '北京'),(20, '研发部', '成都'),(30, '销售部', '重庆'),(40, '运维部', '深圳');-- 创建员工表
create table `tb_emp`
(
`eno` int not null comment '员工编号',
`ename` varchar(20) not null comment '员工姓名',
`job` varchar(20) not null comment '员工职位',
`mgr` int comment '主管编号',
`sal` int not null comment '员工月薪',
`comm` int comment '每月补贴',
`dno` int not null comment '所在部门编号',
primary key (`eno`),
constraint `fk_emp_mgr` foreign key (`mgr`) references tb_emp (`eno`),
constraint `fk_emp_dno` foreign key (`dno`) references tb_dept (`dno`)
);-- 插入14个员工
insert into `tb_emp` values (7800, '张三丰', '总裁', null, 9000, 1200, 20),(2056, '乔峰', '分析师', 7800, 5000, 1500, 20),(3088, '李莫愁', '设计师', 2056, 3500, 800, 20),(3211, '张无忌', '程序员', 2056, 3200, null, 20),(3233, '丘处机', '程序员', 2056, 3400, null, 20),(3251, '张翠山', '程序员', 2056, 4000, null, 20),(5566, '宋远桥', '会计师', 7800, 4000, 1000, 10),(5234, '郭靖', '出纳', 5566, 2000, null, 10),(3344, '黄蓉', '销售主管', 7800, 3000, 800, 30),(1359, '胡一刀', '销售员', 3344, 1800, 200, 30),(4466, '苗人凤', '销售员', 3344, 2500, null, 30),(3244, '欧阳锋', '程序员', 3088, 3200, null, 20),(3577, '杨过', '会计', 5566, 2200, null, 10),(3588, '朱九真', '会计', 5566, 2500, null, 10);-- 查询员工及其主管的姓名insert into tb_emp values (8899, '骆昊', '分析师', 7800, 9000, 5000, 20);-- 查询月薪最高的员工姓名和月薪 ---> 至少给出3种写法
-- 方法一:排序法(不推荐)
select ename,salfrom tb_emporder by sal desclimit 1;-- 方法二:嵌套查询
select ename,salfrom tb_empwhere sal = (select max(sal)from tb_emp);-- 方法三:all / any
select ename,salfrom tb_empwhere sal >= all(select salfrom tb_emp);-- 方法四:计数法
-- 推广到找工资的第几名或者工资的前几名
select ename,salfrom tb_emp as t1where (select count(*)from tb_emp as t2where t2.sal > t1.sal) = 0;-- 方法五:存在性判断
select ename,salfrom tb_emp as t1where not exists (select 'x'from tb_emp as t2where t2.sal > t1.sal);-- 查询月薪前3名的员工的姓名和月薪
select ename,salfrom tb_emp as t1where (select count(*)from tb_emp as t2where t2.sal > t1.sal) < 3order by sal desc;-- 查询员工的姓名和年薪(年薪=(sal+comm)*13)
select ename,(sal + coalesce(comm, 0)) * 13 as ann_salfrom tb_emp;-- 查询部门的编号和人数
select dno,count(*) as totalfrom tb_empgroup by dno;-- 查询部门人数超过5个人的部门的编号和人数
select dno,count(*) as totalfrom tb_empgroup by dno
having total > 5;-- 查询所有部门的名称和人数
select dname,count(eno) as totalfrom tb_dept left join tb_empon tb_dept.dno = tb_emp.dnogroup by tb_dept.dno;select dname,coalesce(total, 0) as totalfrom tb_dept left join (select dno,count(*) as totalfrom tb_empgroup by dno) as ton tb_dept.dno = t.dno;-- 查询月薪超过平均月薪的员工的姓名和月薪
select ename,salfrom tb_empwhere sal > (select avg(sal) from tb_emp);-- 查询月薪超过其所在部门平均月薪的员工的姓名、部门编号和月薪
-- Error Code: 1052. Column 'dno' in field list is ambiguous
select ename,dno,salfrom tb_emp as t1natural join (select dno,avg(sal) as avg_salfrom tb_empgroup by dno) as t2where sal > avg_sal;-- 查询部门中月薪最高的人姓名、月薪和所在部门名称
select ename,sal,dnamefrom tb_emp natural join tb_deptwhere (dno, sal) in (select dno,max(sal) as max_salfrom tb_empgroup by dno);select ename,sal,dnamefrom tb_emp natural join tb_dept natural join (select dno,max(sal) as max_salfrom tb_empgroup by dno) as tmpwhere sal = max_sal;select ename,sal,dnamefrom tb_emp inner join tb_depton tb_emp.dno = tb_dept.dnoinner join (select dno,max(sal) as max_salfrom tb_empgroup by dno) as tmpon tb_emp.dno = tmp.dnowhere sal = max_sal;-- 查询主管的姓名和职位
select ename,jobfrom tb_emp as t1where exists (select 'x'from tb_emp as t2where t1.eno = t2.mgr);select distinct t1.ename,t1.jobfrom tb_emp as t1 inner join tb_emp as t2on t1.eno = t2.mgr;select ename,jobfrom tb_empwhere eno in (select distinct mgrfrom tb_empwhere mgr is not null);-- 查询普通员工的姓名和职位
select ename,jobfrom tb_emp as t1where not exists (select 'x'from tb_emp as t2where t1.eno = t2.mgr);select ename,jobfrom tb_empwhere eno not in (select distinct mgrfrom tb_empwhere mgr is not null);-- 查询主管和普通员工的平均月薪
select tag,avg(sal) as avg_salfrom (select sal,case when exists (select 'x'from tb_emp as t2where t1.eno = t2.mgr)then '主管'else '普通员工'end as tagfrom tb_emp as t1) as tmpgroup by tag;-- 查询月薪排名4~6名的员工排名、姓名和月薪
select t1.*from (select @x := @x + 1 as r,ename,salfrom tb_emporder by sal desc) as t1, (select @x := 0) as t2where r between 4 and 6;-- 窗口函数
-- 排名函数:rank() / dense_rank() / row_number()
select r1,ename,salfrom (select ename,sal,rank() over (order by sal desc) as r1,dense_rank() over (order by sal desc) as r2,row_number() over (order by sal desc) as r3from tb_emp) as tmpwhere r1 between 4 and 6;-- 查询每个部门月薪排前2名的员工姓名、月薪和部门编号
select ename,sal,dnofrom tb_emp as t1where (select count(*)from tb_emp as t2where t1.dno = t2.dno and t2.sal > t1.sal) < 2order by dno asc, sal desc;-- 窗口函数
select ename,sal,dnofrom (select ename,sal,dno,rank() over (partition by dno order by sal desc) as rfrom tb_emp) as tmpwhere r <= 2;#### 练习提升题create database `demo1` default charset utf8mb4;use `demo1`;drop table if exists `tb_order`;create table `tb_order` (
`id` int not null,
`order_no` varchar(20) not null comment '订单编号',
`user_id` varchar(50) not null comment '用户ID',
`order_date` date not null comment '下单日期',
`store` varchar(50) not null comment '店铺ID',
`product` varchar(50) not null comment '商品ID',
`quantity` int not null comment '购买数量',
primary key (`id`)
) engine=innodb comment='订单表';lock tables `tb_order` write;insert into `tb_order` values (1,'d001','customera','2018-01-01','storea','proda',1),(2,'d001','customera','2018-01-01','storea','prodb',1),(3,'d001','customera','2018-01-01','storea','prodc',1),(4,'d002','customerb','2018-01-12','storeb','prodb',1),(5,'d002','customerb','2018-01-12','storeb','prodd',1),(6,'d003','customerc','2018-01-12','storec','prodb',1),(7,'d003','customerc','2018-01-12','storec','prodc',1),(8,'d003','customerc','2018-01-12','storec','prodd',1),(9,'d004','customera','2018-01-01','stored','prodd',2),(10,'d005','customerb','2018-01-23','storeb','proda',1);unlock tables;drop table if exists `tb_product`;create table `tb_product` (
`prod_id` varchar(50) not null comment '商品ID',
`category` varchar(50) not null comment '种类',
`color` varchar(10) not null comment '颜色',
`weight` decimal(10,2) not null comment '重量',
`price` int not null comment '价格',
primary key (`prod_id`)
) engine=innodb comment='商品表';lock tables `tb_product` write;insert into `tb_product` values ('proda','catea','yellow',5.60,100),('prodb','cateb','red',3.70,200),('prodc','catec','blue',10.30,300),('prodd','cated','black',7.80,400);unlock tables;drop table if exists `tb_store`;create table `tb_store` (
`store_id` varchar(50) not null comment '店铺ID',
`city` varchar(20) not null comment '城市',
primary key (`store_id`)
) engine=innodb comment='店铺表';lock tables `tb_store` write;insert into `tb_store` values ('storea','citya'),('storeb','citya'),('storec','cityb'),('stored','cityc'),('storee','cityd'),('storef','cityb');unlock tables;-- 查出购买总金额不低于800的用户的总购买金额,总订单数和总购买商品数,订单号相同的算作一单。
select  sum(quantity*price) as '总购买金额',count(distinct order_no) as '总订单数',count(distinct product) as '总购买数'from tb_order inner join tb_product on tb_order.product = tb_product.prod_idgroup by user_idhaving sum(quantity*price) >= 800;-- 查出所有城市(包含无购买记录的城市)的总店铺数,总购买人数和总购买金额。
select city as 城市,count(distinct store_id) as 总店铺数,count(distinct user_id) as 总购买人数,sum(quantity*price) as 总购买金额from tb_store left join tb_order on tb_store.store_id = tb_order.storeleft join tb_producton tb_order.product = tb_product.prod_idgroup by city;
-- 查出购买过"catea"产品的用户和他们的平均订单金额,订单号相同的算作一单。
select user_id as '用户名',sum( quantity*price) / count(distinct order_no ) as '平均订单金额'from tb_order inner join tb_producton tb_order.product = tb_product.prod_idwhere  category = 'catea'group by user_id;### MySQL 5 留存率与选课系统查询-- 创建用户登录日志表
create database homework ;
use homework;
create table `tb_user_login`
(
`user_id` varchar(300) comment '用户ID',
`login_date` date comment '登录日期'
) engine=innodb comment='登录日志表';-- 插入数据
insert into `tb_user_login` (`user_id` , `login_date`)
values('A', '2019/9/2'),('A', '2019/9/3'),('A', '2019/9/4'),('B', '2019/9/2'),('B', '2019/9/4'),('B', '2019/9/10'),('C', '2019/1/1'),('C', '2019/1/2'),('C', '2019/1/30'),('C', '2019/9/3'),('C', '2019/9/4'),('C', '2019/9/5'),('C', '2019/9/11'),('C', '2019/9/12'),('C', '2019/9/13');-- 任务1:查询连续3天登录的用户ID。
-- 方法1
use homework;
Select distinct user_idfrom tb_user_login  where  (user_id ,date_add(login_date,interval 1 day)) in (select * from tb_user_login) and (user_id ,date_add(login_date,interval 2 day)) in (select * from tb_user_login);-- 方法2
select distinct `user_id`
from (select `user_id`, `login_date`,dense_rank() over (partition by `user_id` order by `login_date`) as `rn`from (select `user_id`, `login_date`from `tb_user_login`group by `user_id`, `login_date`) as temp
) as temp
group by `user_id`, subdate(`login_date`, `rn`)
having count(*) >= 3;-- 任务2:查询每天新增用户数以及他们次日留存率和三十日留存率。
-- 查询每天新增用户数以及他们次日留存率和三十日留存率。
-- 方法1:
select `first_login`, count(distinct t1.`user_id`) as 新增用户数, count(distinct t2.`user_id`) / count(distinct t1.`user_id`) as 次日留存率, count(distinct t3.`user_id`) / count(distinct t1.`user_id`) as 三十日留存率
from (select `user_id`, `login_date`,min(`login_date`) over (partition by `user_id` order by `login_date`) as `first_login` from `tb_user_login`
) as t1
left join `tb_user_login` as t2
on t1.`user_id`=t2.`user_id` and datediff(`first_login`, t2.`login_date`)=-1
left join `tb_user_login` as t3
on t1.`user_id`=t3.`user_id` and datediff(`first_login`, t3.`login_date`)=-29
group by `first_login`;-- 方法2:
select `first_login`,count(distinct `user_id`) as 新增用户数,sum(case datediff(`login_date`, `first_login`) when 1 then 1 else 0 end) / count(distinct `user_id`) as 次日留存率,sum(case datediff(`login_date`, `first_login`) when 29 then 1 else 0 end) / count(distinct `user_id`) as 三十日留存率
from (select `user_id`, `login_date`,min(`login_date`) over (partition by `user_id` order by `login_date`) as `first_login` from `tb_user_login`
) as t1
group by `first_login`;#### Practice
-- 第一题
use homework;
create table `tb_result` (`rq` date not null,`sf` char(1) not null
) engine=innodb;insert into `tb_result` values ('2017-04-09','胜'),('2017-04-09','胜'),('2017-04-09','负'),('2017-04-09','负'),('2017-04-10','胜'),('2017-04-10','负'),('2017-04-10','胜');-- 用上面的表查询出如下所示的结果。
-- | date       | win  | los  |
-- | ---------- | ---- | ---- |
-- | 2017-04-09 | 2    | 2    |
-- | 2017-04-10 | 2    | 1    |-- 方案1
select distinct rq as date,sum(if(sf = '胜',1,0)) as  win,sum(if(sf = '负',1,0)) as  losfrom tb_resultgroup by rq;   -- 方案2   select distinct rq as date,sum( case sf when '胜' then  1  else 0   end ) as  win,sum( case sf when '负' then  1  else 0   end ) as  losfrom tb_resultgroup by rq;    -- 第二题
create table `tb_course`
(
`course_id` int unsigned not null comment '课程编号',
`course_name` varchar(50) not null comment '课程名称',
primary key (`course_id`)
) engine=innodb;insert into `tb_course` values (1, 'Python'),(2, 'Java'),(3, 'Database'),(4, 'JavaScript');create table `tb_open_date`
(
`month` char(6) not null comment '开课日期',
`course_id` int unsigned not null comment '课程编号'
) engine=innodb;insert into `tb_open_date` values('202106', 1),('202106', 3),('202106', 4),('202107', 4),('202108', 2),('202108', 4);-- 用上面的表查询出如下所示的结果。
-- | course_name | Jun | Jul | Aug |
-- | ----------- | --- | --- | --- |
-- | Python      |  o  |  x  |  x  |
-- | Java        |  x  |  x  |  o  |
-- | Database    |  o  |  x  |  x  |
-- | JavaScript  |  o  |  o  |  o  |
select  t1.course_name ,case  right(month,1)  when  '6'     then  'o'  else   'X'  end as Jun,case  right(month,1)  when  '7'     then  'o'  else   'X'  end as Jul,case  right(month,1)  when  '8'     then  'o'  else   'X'  end as Augfrom  tb_course as t1 inner join   tb_open_date  as t2  on  t1.course_id = t2.course_id -- group by course_nameorder by  t1.course_id asc;-- 第三题
create table `tb_table1`
(
`userid` int unsigned not null,
`username` varchar(20) not null,
primary key (`userid`)
);insert into `tb_table1` values(1, '张三'),(2, '李四'),(3, '王五'),(4, '赵大'),(5, '孙二');create table `tb_table2`
(
`month` varchar(20) not null,
`userid` int unsigned not null,
`ye` int not null
);drop table `tb_table2`;
insert into `tb_table2` values('一月份', 1, 10),('一月份', 2, 10),('一月份', 3, 5),('一月份', 1, 5),('二月份', 2, 8),('二月份', 2, 7),('二月份', 4, 9),('三月份', 3, 8),('三月份', 5, 6);-- 用上面的tb_table1和tb_table2查询出如下所示的结果。
-- +----------+-----------+-----------+-----------+
-- | 用户名    | 一月份     | 二月份     | 三月份     |
-- +----------+-----------+-----------+-----------+
-- | 张三      |        15 |         0 |         0 |
-- | 李四      |        10 |        15 |         0 |
-- | 王五      |         5 |         0 |         8 |
-- | 赵大      |         0 |         9 |         0 |
-- | 孙二      |         0 |         0 |         6 |
-- +----------+-----------+-----------+-----------+select username as 用户名,sum(case month when '一月份' then ye  else 0  end ) as '一月份',sum(case month when '二月份' then ye  else 0  end)  as '二月份',sum(case month when '三月份' then ye  else 0  end)  as '三月份'from  tb_table1 natural join tb_table2group by username;### MYSQL  补充中位数### MySQL 6  视图use hrs;
create table tb_sales
(
sales_id  int unsigned   auto_increment,
sales_date date not null comment '销售日期',
sales_area varchar(20) not null comment '销售区域',
sales_channel varchar(20) not null comment '销售渠道',
order_no varchar(50) not null comment '销售订单',
brand varchar(20) not null comment '品牌',
unite_price integer  not null comment '售价',
sales_quantity integer not null comment '销售数量'
primary key (sales_id)) engine=innodb comment '销售明细表';load data local  infile '"C:\Users\Lenovo\Desktop\2020年销售数据.csv"'
into table tb_sales
fields  terminated by  ','
lines terminated by '\n';-- Error Code: 3948. Loading local data is disabled; this must be enabled on both the client and server sides--   ##### 表中的数据导入到数据库和数据库的内容导出到表中 ?
load data local  infile '"C:\Users\Lenovo\Desktop\2020年销售数据.csv"'
into table tb_sales
fields  terminated by  ','
lines terminated by '\n';-- 1 .查询月度销售金额select month (sales_date) as 月份,sum(unite_price*sales_quantity) as  销售额from tb_salesgroup by month(sales_date);-- 补充:计算按月环比,-- 环比=(本期数-上期数)/上期数×100%
-- 同比=(本期数-同期数)÷同期数×100%-- year /quarter/month/day / weekday--  窗口函数lag(,数字,默认值0) 可以往回拿几条数据
-- lead( ,数字,默认值) 往后拿几条数据
select 月份,(本月销售额-上月销售额)/上月销售额  as 环比from (select  月份,销售额 as 本月销售额,lag(销售额,1)  over (order by 月份 asc ) as 上月销售额from(select month (sales_date) as 月份,sum(unite_price*sales_quantity) as  销售额from tb_salesgroup by month(sales_date)) as temp) as temp;-- 2. 查询各品牌对销售额贡献的占比
-- 方法1 定义变量,求出总销售额
select @total_sales := sum(unite_price*sales_quantity) as 销售额from tb_sales;
-- 计算各品牌的销售额贡献占比
select brand as  品牌,sum(unite_price*sales_quantity)/@total_sales as 销售贡献占比from tb_salesgroup by brand;    #这些数据是正确的-- 方法2 直接用一个,不分开写
select brand as  品牌,sum(unite_price*sales_quantity)/(select @total_sales := sum(unite_price*sales_quantity) as 销售额from tb_sales) as 销售贡献占比from tb_salesgroup by brand; -- with rollup      -- 算总计--  方法三: 把需要算的东西提前计算好,加入一些辅助列--  视图:查询的快照(命名一个一有的查询,下次可以通过这个名字执行对应的查询)
use hrs;
-- 创建视图
create view vw_sales_detail
as  -- 别名
select year(sales_date) as 'year',  -- 年quarter(sales_date) as 'quarter',  -- 季度month(sales_date) as sales_month,   -- 月day(sales_date) as sales_day,    -- 日weekday(sales_date) as sales_weekday,  -- 星期几sales_channel,    -- 起到order_no,   --    brand,     -- 品牌sales_quantity,    -- 数量unite_price*sales_quantity as sales_amount   -- 交易金额from tb_sales;-- 查询视图
select * from vw_sales_detail;-- 也可以这样,创建或替换视图 ,加入一些条件
create  view vw_sales_detail_new
as  -- 别名
select year(sales_date) as 'year',  -- 年quarter(sales_date) as 'quarter',  -- 季度month(sales_date) as sales_month,   -- 月day(sales_date) as sales_day,    -- 日weekday(sales_date) as sales_weekday,  -- 星期几sales_channel,    -- 起到order_no,   --    brand,     -- 品牌case when unite_price <300 then 'low' when unite_price <800 then 'middle' else 'high'  end  as  price_segment,  -- 对价格进行等级划分sales_quantity,    -- 数量unite_price*sales_quantity as sales_amount   -- 交易金额from tb_sales;    -- 1 .查询月度销售金额
select  sales_month,sales_amountfrom vw_sales_detail_newgroup by sales_month;-- 借助视图来计算销售额月环比
-- 环比=(本期数-上期数)/上期数×100%
select  月份,(月销售额-上月销售额)/上月销售额  as 月环比from (select 月份,月销售额,   lag(月销售额,1) over (order  by 月份 asc )as  上月销售额from (select  sales_month as 月份,sum(sales_amount) as 月销售额from vw_sales_detail_newgroup by sales_month) as temp  ) as temp;-- 2. 查询各品牌对销售额贡献的占比
select brand,sales_amount/sum(sales_amount) as 销售额贡献from vw_sales_detail_newgroup by brand;-- 3. 查询各销售区域月度销售额  --- 宽表
-- 方法1 没有使用视图,再原表中进行操作
select sales_area as 渠道,month(sales_date)  as 月份,sum(case  month(sales_date) when  1 then unite_price*sales_quantity  else 0 end ) as '1月销售额',sum(case  month(sales_date)  when  2 then unite_price*sales_quantity  else 0 end ) as '2月销售额',sum(case  month(sales_date) when  3 then unite_price*sales_quantity  else 0 end ) as '3月销售额',sum(case  month(sales_date) when  4 then unite_price*sales_quantity  else 0 end ) as '4月销售额',sum(case  month(sales_date) when  5 then unite_price*sales_quantity  else 0 end ) as '5月销售额',sum(case  month(sales_date) when  6 then unite_price*sales_quantity  else 0 end ) as '6月销售额',sum(case  month(sales_date) when  7 then unite_price*sales_quantity  else 0 end ) as '7月销售额',sum(case  month(sales_date) when  8 then unite_price*sales_quantity else 0 end ) as '8月销售额',sum(case  month(sales_date) when  9 then unite_price*sales_quantity  else 0 end ) as '9月销售额',sum(case  month(sales_date) when  10 then unite_price*sales_quantity  else 0 end ) as '10月销售额',sum(case  month(sales_date) when  11 then unite_price*sales_quantity  else 0 end ) as '11月销售额',sum(case  month(sales_date) when  12 then unite_price*sales_quantity  else 0 end ) as '12月销售额'from tb_salesgroup by sales_area;-- 方法2 使用视图,先根据需要的数据,键视图表
-- 3. 查询各销售区域月度销售额  --- 宽表
create view  vw_sales_detail_add
as select sales_area,month(sales_date) as sales_month,unite_price * sales_quantity as sales_amountfrom tb_sales;
--  3. 查询各销售区域月度销售额  --- 宽表
select sales_area,sum(case  sales_month when  1 then  sales_amount else 0 end ) as '1月销售额',sum(case  sales_month  when  2 then sales_amount else 0 end ) as '2月销售额',sum(case  sales_month when  3 then sales_amount else 0 end ) as '3月销售额',sum(case  sales_month when  4 then sales_amount  else 0 end ) as '4月销售额',sum(case  sales_month when  5 then sales_amount  else 0 end ) as '5月销售额',sum(case  sales_month when  6 then sales_amount  else 0 end ) as '6月销售额',sum(case  sales_month when  7 then sales_amount  else 0 end ) as '7月销售额',sum(case  sales_month when  8 then sales_amount else 0 end ) as '8月销售额',sum(case  sales_month when  9 then sales_amount else 0 end ) as '9月销售额',sum(case  sales_month when  10 then sales_amount else 0 end ) as '10月销售额',sum(case  sales_month when  11 then sales_amount  else 0 end ) as '11月销售额',sum(case  sales_month when  12 then sales_amount  else 0 end ) as '12月销售额'from vw_sales_detail_addgroup by sales_area;-- 4. 查询各渠道品牌销量  -- 宽表select sales_channel as 销售渠道,sum(case  brand  when  '八匹马' then sales_quantity else 0 end  )  as '八匹马',sum(case  brand when   '皮皮虾' then sales_quantity else 0 end  )as '皮皮虾',sum(case  brand when  '壁虎' then sales_quantity else 0 end  ) as '壁虎',sum(case  brand when  '花花姑娘' then sales_quantity else 0 end)  as '花花姑娘',sum(case  brand when  '啊哟喂' then sales_quantity  else 0 end ) as '啊哟喂'from vw_sales_detail_newgroup by 销售渠道;-- 5. 不同价格区间产品的月度销量
select price_segment  as 价格区间,sales_month  as 月份,sum(sales_quantity) as 销量
from vw_sales_detail_new
group by sales_month ;-- 按照不同的价格区间做月度销量分析
-- 写成宽表
-- 根据价格段进行分组
use hrs;
select sales_month as 月份,sum(case  price_segment when  'low' then sales_quantity  else  'o' end) as '低价销售量', sum(case  price_segment when  'middle' then sales_quantity  else  'o' end) as '中价销售量', sum(case  price_segment when  'high' then sales_quantity  else  'o' end) as '高价销售量'from vw_sales_detail_newgroup by sales_month;
use hrs;### MySQL 7  函数use school;
-- 函数 :功能上相对独立且会被重复使用的代码     --- 用户自定义函数
-- 如果学院介绍超过了50个字符,截断它后补上省略号
-- 如果学院介绍没有超过50个字符,就完整到的显示出来
select col_id,col_name,case when char_length(col_intro) > 50 then   concat( left(col_intro,50) , '......' ) else  col_intro  end as col_introfrom tb_college;-- 修改代码终止符--函数只能的分号表示一个语句的结束,而不是整个代码的结束delimiter $$--  创建函数  User Defined Function
-- reads sql data 如果使用了sql语句,在最后面要加一个说明,没有使用sql语句,就写no sql-- 自定义一个不需要传参的函数delimiter $$
create function say_hello()  returns varchar(16383) reads sql data no sql
begin return 'hello,world';
end $$
delimiter ; use school;
-- 练习  from dual 是一个虚拟表,只是让代码完整。
select say_hello() from dual;-- 自定义一个需要传参的函数
delimiter $$
create function say_name( tb_name varchar(30))  returns varchar(16383) reads sql data no sql
begin return  concat('hello, ',tb_name , '!');
end $$
delimiter ;
select say_name('tom') from dual;
select say_name('kaixing') from dual;-- 把字符串截断变成函数
delimiter $$
create function truncate_string(content varchar(16383),max_length int unsigned
)  returns varchar (16383) no sql
begin if char_length(content) > max_length  then return   concat(left(content,max_length),'......');else return content;end   if;end $$
delimiter ;-- 可以定义变量,让函数变得更简洁delimiter $$
create function truncate_string(content varchar(16383),max_length int unsigned
)  returns varchar (16383) no sql
begin declare result varchar(16383) default content;if char_length(content) > max_length  then set result=concat(left(content,max_length),'......');end  if;return result;end $$
delimiter ;use school;-- 使用自定义函数来解决前面的问题
select col_id,col_name,truncate_string(col_intro,50)from tb_college ;##### practice -- 杨过 --> 杨*-- 杨不悔-- > 杨*悔-- 东方不败--> 东**败##### Practice 2 YY-- 1:函数和过程有什么用?二者有什么区别?-- 2:base64是什么?-- 1. BASE64编码的原理和应用场景
--  2. 自定义函数实现保护姓名隐私
--  3. 函数和过程有什么作用?二者有何区别?-- 4. 绘制school数据库对应的ER图drop function if exists protect_name;use school;delimiter $$create function protect_name(thy_name varchar(16383))returns varchar(16383) no sqlbegindeclare result varchar(16383) default thy_name;if  char_length(thy_name) = 2 then set result = concat(left(thy_name,1),'*');else  set result = concat(left(thy_name,1),repeat('*',(char_length(thy_name)-2)),right(thy_name,1));end  if;return result;end$$delimiter ;select protect_name(stu_name)from tb_student;### MySQL 8 JSON数据查询
use hrs;
-- json 对象的数据查询
drop table if exists `tb_test`;create table `tb_test`
(
user_id  bigint unsigned,
login_info json,
primary key (`user_id`)
)engine=innodb;insert into `tb_test` values (1, '{"tel": "13122335566", "QQ": "654321", "wechat": "jackfrued"}'),(2, '{"tel": "13599876543", "weibo": "wangdachui123"}'),(3, '{"wechat": "luohao"}');select user_id,json_unquote(json_extract(login_info, '$.tel')) as 手机号from tb_test; select `user_id`,json_unquote(json_extract(`login_info`, '$.tel')) as 手机号,json_unquote(json_extract(`login_info`, '$.wechat')) as 微信
from `tb_test`;select `user_id`,`login_info` ->> '$.tel' as 手机号,`login_info` ->> '$.wechat' as 微信
from `tb_test`;--*****  用户打标签create table `tb_tags`
(
`tag_id` int unsigned not null comment '标签ID',
`tag_name` varchar(20) not null comment '标签名',
primary key (`tag_id`)
) engine=innodb;insert into `tb_tags` (`tag_id`, `tag_name`)
values(1, '70后'),(2, '80后'),(3, '90后'),(4, '00后'),(5, '爱运动'),(6, '高学历'),(7, '小资'),(8, '有房'),(9, '有车'),(10, '爱看电影'),(11, '爱网购'),(12, '常点外卖');drop table  if exists `tb_users_tags`;
create table `tb_users_tags`
(
`user_id` bigint unsigned not null comment '用户ID',
`user_tags` json not null comment '用户标签'
) engine=innodb;insert into `tb_users_tags` values (1, '[2, 6, 8, 10]'),(2, '[3, 10, 12]'),(3, '[3, 8, 9, 11]');delete from tb_users_tags where user_id=1;-- 查询爱看电影(有10这个标签)的用户ID
select user_idfrom tb_users_tagswhere 10 member of (user_tags -> '$'); -- $代表的是user_tags的数组-- 查询爱看(10)电影的80后(2)
-- json_contains( 列名-> '$' ,'[ 2,10]')  前面的数组有么有包含后面的数组(超集)select user_idfrom tb_users_tagswhere json_contains (user_tags -> '$','[2,10]'); -- 查询爱看电影或80或90后的用户ID
-- json_overlaps(user_tags ->'$','[2,3,10]' ) $与[2,3,10] 这两个是不是有交集,有交集就留下来select user_idfrom tb_users_tagswhere json_overlaps(user_tags -> '$','[2,3,10]');### MySQL 9 过程与索引-- 科普知识-- * 把明文变成密文的过程叫加密,把密文变回明文的过程叫做解密--  对称加密:加密和解密是同一个密密匙-- 非对称加密:加密和集美不是一个密钥,有公钥和私钥之分。--  摘要: 通过一个单向哈希函数给一个对象生成一个签名(指纹)。-- MD5/SHA1/SHA256-- 编码:把一种表示方式转换成另外的表示方式,逆操作叫做解码。-- 单机 —> 多级    复杂均衡   分布式集群   数据如何同步??
-- 事务transaction - 把多个写数据的操作(增删改)视为不可分割的原子性操作,要么全都成功,要么全都失败。 程序 :procedure-- 过程学习-- 互联网会因为遭遇高并发和大流量,所以不推荐使用存储过程,使用存储过程会增加use hrs;-- 工资普调-- 规则 : 10部门 +500, 20部门+1000 ,30部门+300 update tb_emp set sal = sal+50 where dno = 10;update tb_emp set sal = sal+1000 where dno = 20;update tb_emp set sal = sal+300 where dno = 30;-- TCL----transction  Control Language-- start transaction /begin /commit /roolback-- 如何判断代码执行是否成功,方法,如果代码出现异常,代码会打断,所有加一个异常处理器,-- 存储过程的参数,两个,一个输入参数in(把信息代入过程中)和输出参数out(把数据带出过程),变量名前面加@表示这个变量是用户自定义的一个变量-- 想要把过程得到的数据,拿出来用,就要加入输出参数,看例2-- 例1-- 使用过程来完成调薪:delimiter $$create procedure sp_upgrade_salary( )   -- 如果需要参数,可以传参。begin declare flag boolean default 1;declare continue handler for sqlexception set flag = 0;start transaction;-- 下面这个三条命令是原子性操作,必须全部成功。要么全部失败update tb_emp set sal = sal+500 where dno = 10;update tb_emp set sal = sal+1000 where dno = 20;update tb_emp set sal = sal+300 where dno = 30;if falg thencommit;elserollback ;end if ;end $$
delimiter ;-- 调用过程的程序
call sp_upgrade_salary();-- mysql必知必会上第24章会讲到使用游标cursor;来抓取二维表数据drop  procedure sp_upgrade_salary # 删除存储过程-- 例2 delimiter $$create procedure sp_upgrade_salary( out avg_sal decimal(10,2))   -- 如果需要参数,可以传参out 是输出参数,通过输出参数,将过程中的数据带出去使用。begin declare flag boolean default 1;declare continue handler for sqlexception set flag = 0;start transaction;-- 下面这个三条命令是原子性操作,必须全部成功。要么全部失败update tb_emp set sal = sal+500 where dno = 10;update tb_emp set sal = sal+1000 where dno = 20;update tb_emp set sal = sal+300 where dno = 30;if falg thencommit;elserollback ;end if ;select avg(sal) into avg_sal from tb_emp;end $$
delimiter ;-- 调用过程存储程序
call sp_upgrade_salary(@x);
select @x;
select @x from tb_emp where sal > @x ;

MySQL 查询题型总结相关推荐

  1. mysql查询字段大小写结果相同,mysql大小写查询不敏感,mysql5.7查询不区分大小写解决方案。

    下面有两条sql,主键查询,在mysql中查询到的结果相同. SELECT* FROM USER WHEREid = 'EM58hdK4nXC';SELECT* FROM USER WHEREid = ...

  2. MySQL查询进阶之多表查询

    一.多表查询 1.引出 2.笛卡尔积 3. 笛卡尔积的解决方法 二.多表查询分类 1.等值连接和非等值连接 2.自连接和非自连接 3.内连接和外连接 SQL92:使用(+)创建连接 SQL99语法实现 ...

  3. smarty mysql_Smarty处理mysql查询数组

    Smarty处理mysql查询数组 MySQL的查询结果一般是一个数组,而不是所有结果集.因此我们需要将结果全部存到数组中进行处理,然后就可以很轻松的再Smarty中使用了. PHP Mysql 代码 ...

  4. MYSQL 查询数据排序数据和分组数据

    在mysql查询过程中,可以对数据进行过滤,也可以对数据进行排序,可以对数据分组,下面分别讲述排序数据和分组数据例子.1,数据的排序 使用 ORDER BYselect * from where id ...

  5. mysql查询解析过程_MySQL查询执行过程详解

    查询是用户通过设置某些查询条件,从表或其他查询中选取全部或者部分数据,以表的形式显示数据供用户浏览.查询是一个独立的.功能强大的.具有计算功能和条件检索功能的数据库对象.MySQL数据库中,MySQL ...

  6. mysql 查询某个日期时间段,每天同一时间段的数据

    mysql 查询某个日期时间段,每天同一时间段的数据: SELECT * FROM t_a01_eltable WHERE DATE_FORMAT(acqtime,'%Y-%m-%d')>='2 ...

  7. php 多条查询结果插入新表,Mysql应用MySQL查询结果复制到新表的方法(更新、插入)...

    <Mysql应用MySQL查询结果复制到新表的方法(更新.插入)>要点: 本文介绍了Mysql应用MySQL查询结果复制到新表的方法(更新.插入),希望对您有用.如果有疑问,可以联系我们. ...

  8. MySQL查询区分大小写

    2019独角兽企业重金招聘Python工程师标准>>> 问题描述: 找出用户名id为'AAMkADExM2M5NjQ2LWUzYzctNDFkMC1h'的用户的数据: select ...

  9. 100G内存下,MySQL查询200G大表会OOM么?

    文章来源:https://sourl.cn/vwDNzn 我的主机内存只有100G,现在要全表扫描一个200G大表,会不会把DB主机的内存用光? 逻辑备份时,可不就是做整库扫描吗?若这样就会把内存吃光 ...

  10. mysql 查询用户最后登陆时间_弄懂mysql:mysql的通信协议

    我准备从mysql的实现出发,将mysql好好理解一下,从他的逻辑结构一层一层出发,感受一下,所以再学第一层之前,要先对mysql整体的逻辑结构有一个初步认识 mysql逻辑架构 整体来说,MySql ...

最新文章

  1. 最大权值闭合子图的证明详解
  2. 阿里云 Ubuntu16.04 部署 LAMP
  3. Leetcode 分类 题解 收集
  4. 网狐棋牌(二) CQueueServiceEvent初步分析
  5. css3 设置多列布局
  6. 机器人 工具坐标系的标定
  7. php继承和重载区别,php继承中方法重载(覆盖)的应用场合
  8. 福大软工1816 · 第二次作业 - 个人项目
  9. 官方 STM32F303ZE Nucleo-144开发板 点亮led
  10. platform_device_add()函数分析
  11. socket.io 中文手册 socket.io 中文文档
  12. 2021数据分析岗疯狂内卷下,给应届校招生的建议:请避开大厂
  13. aspxgridview将所选项导出ASPxGridViewExporter1
  14. Android系统如何录制屏幕(录制成mp4格式)
  15. 计算机网络:王道考研
  16. 公司要一个网站,是选模板建站还是定制化建站?
  17. 液晶显示屏简介以及与CRT显示屏的对比
  18. [今日阅读] [TSE 2019] - Mining Fix Patterns for FindBugs Violations
  19. pdf添加水印的方法,pdf加水印步骤
  20. Inserting操作导致死锁Oracle

热门文章

  1. 理解一下 GK Zone 20 与GK Zone 20N的区别
  2. 第一章 Python数据模型
  3. 网页进行QQ聊天简单应用
  4. gite改提交的用户名称
  5. 制作Lightbox效果
  6. 诡异大阳飙升动因何在
  7. wpf DataGrid 绑定数据源后多一列
  8. stress模拟CPU使用100%
  9. c语言编程温度转换源,c语言编程,将华氏温度转换成摄氏温度。转换公式为:c=5/9 * (f-32),其中f代表华氏温度...
  10. PyTorch 1.7 Video 初体验(Video Datasets,Video IO,Video Classification Models,Video Transform)