Catalogue
摘要
MySQL练习题,基于不同的场景模拟进一步加强MySQl知识点练习~
MySQL练习 - 场景模拟初级篇
薪水涨幅升序
[题目]
现在有两个表:
- 雇员表:记录了雇员基本信息,字段包括:雇员编号、出生日期、姓名、性别、雇用日期
- 薪水表:记录了雇员的薪水金额以及签订周期,字段包括:雇员编号、薪水、起始日期、结束日期
- 两张表通过雇员编号进行连结
现在需要查找当前所有雇员入职以来的薪水涨幅,给出雇员编号以及其对应的薪水涨幅,并按照薪水涨幅进行升序
注意:薪水表中最大结束日期为2004-01-01,说明结束日期在此之前的均表示为已离职员工
1 | #建雇员表 |
[思路]
- 读题:查找当前所有雇员入职以来的薪水涨幅,给出雇员编号以及对应的薪水涨幅,并按照薪水涨幅进行升序
- 解题:
- 输出为:雇员编号、薪水涨幅,且按照薪水涨幅进行升序排列
- 限定条件为:当前雇员,即结束日期为表中最大日期2004 - 01 - 01
- 薪水涨幅 = 当前薪水 - 入职薪水 ,根据最终输出要求,先分别找出雇员编号+当前薪水作为临时表a,在找出雇员编号+入职薪水作为临时表b,最后将临时表a和临时表b进行join方能运算出结果
1 |
|
比前一天高的数据
[题目]
"日销"表记录了某公司每天的营业额,字段有:id,日期,营业额(万元)
现在需要找出所有比前一天(昨天)营业额更高的数据
1 | #创建表 |
[思路]
- 读题:找出所有营业额比**前一天(昨天)**营业额更高的数据
- 解题:
- 比较同一个表内不同行的内容需要自join,连结条件为日期差为1天
- 日期比较方式1:datediff(日期1,日期2) ,即日期1 - 日期2的天数差
- 日期比较方式2:timestampdiff(day/hour/second,日期1,日期2),即日期2 - 日期1的差,与上面相反
- 结果限定条件为:营业额比前一天的高
- 比较同一个表内不同行的内容需要自join,连结条件为日期差为1天
1 | #datediff |
最小的n个数
[题目]现在有两个表:
- 学生表里记录了学生的学号、入学时间等信息,字段有:姓名、学号、班级、入学时间、年龄、专业
- 成绩表里记录了学生选课成绩的信息,字段有:学号、课程号、分数
- 两张表通过学号进行连结
现在需要:
- 筛选出2017年入学的"计算机"专业年龄最小的3位同学,输出格式为姓名、年龄
- 统计每个班各位同学成绩平均分大于80分的人数和人数占比
1 | #创建学生表 |
[解题1]
- 读题:筛选出2017年入学的"计算机"专业年龄最小的3位同学,输出格式为姓名、年龄
- 解题:
- 限定条件1:2017年入学,根据入学时间的年份进行限定
- 限定条件2:专业 - 计算机
- 限定条件3:年龄最小的3位同学,根据年龄进行倒序排列,limit输出前3行
1 | select name,age |
[解题2]
- 读题:统计每个班各位同学成绩平均分大于80分的人数和人数占比
- 解题:
- 每位同学成绩平均分 > 80,成绩表根据 id 进行分组算出平均分,作为临时表
- 统计每个班,则需要按照班级来分组,班级信息在学生表,而平均分信息在临时表,需要两表进行join
- 输出为人数、人数占比,使用case when 进行统计平均分大于80的人数,以及后续的计算占比
1 | select |
连续出现n次的数据
[题目]
成绩表记录了学生id以及分数,字段有:id、score
先需要查找出所有至少连续出现3次的分数
1 | #创建表 |
[思路]:
- 读题:查找出所有、至少、连续出现3次的分数
- 解题:
- 注意:这个题目要求学号必须连续,以下语句才能正确执行
- 比较同一个表里的同一列的不同行的数据,需要自join
- 连续出现3次,意思就是学号a的成绩=学号a+1的成绩=学号a+2的成绩,说明需要自join3次
- 输出为这个至少出现3次的成绩是多少,distinct去除重复
1 | select distinct a.score |
课程满意度分析
[题目]
- 满意度记录了教师和学生对课程的满意程度,字段有:教师编号、学生编号、是否满意;
- 其中是否满意代表老师和学生对课程的评价,值"是"代表教师和学生都满意
- 用户表记录了学校教师和学生的信息,字段有:用户编号、是否在系统、角色
- 每个用户有唯一的编号
- 是否在系统表示 这个用户是否还在这所学校里
- 角色表示这个用户是教师还是学生
- 满意度表中的学生编号、教师编号与用户表的编号联结
现需要分析学校里人员对课程的满意度
1 | #创建满意度表 |
[思路]
- 读题:现需要分析学校里人员对课程的满意度
- 解题:
- 满意度信息在满意度表中,人员信息在用户表中,需要两表联结
- 满意度计算:(对课程都满意且在系统中的教师和学生) / (在系统中的所有用户)
- 限定条件1:是否在系统 - 是
- 限定条件2:满意度 - 是
- 找出在系统中的所有id,然后筛选满意度表中的数据,再进行计算
1 | select sum(if(a.satisfied = "是",1,0)) / count(a.satisfied) as "课程满意度" |
红包领取情况
[题目]
- 用户活跃表记录了用户的登录信息,字段有:登录日期、用户ID、新用户
- 其中新用户列的值为0、1;值为0为老用户、值为1为新用户
- 领取红包表里记录了用户领取红包的信息,字段有:抢红包日期、抢红包时间、用户id、金额
现需要分析以下问题:
- 计算2019年6月1日至今,每天DAU (即活跃用户,定义:有登录的用户)
- 分析每天领红包的用户数、人均领取金额、人均领取次数,其中还有用户属性以及领取红包未登录的情况
- 分析每个月按领红包取天数为1、2、3…30、31天区分,计算取每个月领取红包的用户数、人均领取金额、人均领取次数
- 分析每个月领过红包用户和未领红包用户的数量
1 | create table dau_users( |
[解题1]
- 读题:计算2019年6月1日至今,每天DAU (即活跃用户,定义:有登录的用户)
- 解题
- 2019年6月1日到今天,限定条件为登录日期 >= 2019年6月1日
- 统计每天的登录用户
1 | select log_date,count(uid) as "DAU-活跃用户" |
[解题2]
- 读题:分析每天领红包的用户数、人均领取金额、人均领取次数,其中还有用户属性以及领取红包未登录的情况
- 解题
- 每天领红包的用户分为三种:新用户、老用户以及领取红包但是未登录的用户,而新用户、老用户的数据统计在用户活跃表中,领取红包但是未登录的用户需要用两表进行联结比对
- 人均领取金额 = 领红包总金额 / 领红包总人数 (去重用户数)
- 人均领取次数 = 总领取次数 / 领红包总人数 (去重用户数)
1 | select c.grabdate, |
[解题3]
- 读题:分析每个月按领红包取天数为1、2、3…30、31天区分,计算取每个月领取红包的用户数、人均领取金额、人均领取次数
- 解题:
- 按照月份进行分组,然后统计该月有多少天有领红包行为,因为领红包日期为字符串格式,所以选用领红包时间列使用month()函数进行分组
- 统计分组后每个月有多少用户领取红包,需要distinct
- 人均领取金额 = 该月份领取红包总金额 / 该月份领取红包用户数 (distinct)
- 人均领取次数 = 该月份总领取红包次数 / 该月份领取红包用户数 (distinct)
1 | select month(g.grab_time) as "月份", |
[解题4]
- 读题:分析每个月 领过红包用户和未领红包用户的数量
- 解题:
- 每个月,即按照月份来分组,month()
- 领过红包用户信息存在领红包表中,而未领红包用户存在用户活跃表中,需要两表联结进行比对,用户活跃表作为 left join 的左表
- 未领取红包用户 = 活跃用户 - 领红包用户
1 | select month(c.grab_time), |
登录统计排序
[题目]
用户登录时间表中记录了用户登录的信息,字段有:用户id、姓名、邮箱、最后登录时间
现需要输出一张表,字段为:姓名、最后登录时间、登录时间排名、登录天数排名
- 登录时间排名:按时间给出每个人的登录次数,登录时间最早为1,依次排下去
- 登录天数排名:按天给出每个人的登录次数,同一天多次登录设定为同一次,最多天数标记为1,之后依次类推
1 | #创建表 |
[思路]
-
读题:现需要输出一张表,字段为:姓名、最后登录时间、登录时间排名、登录天数排名
- 登录时间排名:按时间给出每个人的登录次数,登录时间最早为1,依次排下去
- 登录天数排名:按天给出每个人的登录次数,同一天多次登录设定为同一次,最多天数标记为1,之后依次类推
-
解题(与出题者给出的答案理解不同,出于我自设定的业务场景):
-
我觉得应该需要给出以下这样的列表
姓名 最后登录时间 最早登录时间 登录时间排名 登录天数 登录天数排名 test1 2007-05-25 14:22:00 2007-02-25 14:17:00 1 2 1 test2 2007-10-25 14:20:00 2007-03-22 16:27:00 2 2 1 test4 2007-11-25 16:31:00 2007-11-25 16:31:00 3 1 2 -
下面语句分开的原因是:这种方式语句需要对要进行排名的列进行先排序,而同时对两列进行排列,会影响第二列的排名不准确,暂时不知道如何处理
-
1 | select a.name,a.最后登录时间,a.最早登录时间, |
持续更新中~