以下为非技术快速入门题目
drop table if exists `user_profile`;
drop table if exists `question_practice_detail`;
drop table if exists `question_detail`;
CREATE TABLE `user_profile` (
`id` int NOT NULL,
`device_id` int NOT NULL,
`gender` varchar(14) NOT NULL,
`age` int ,
`university` varchar(32) NOT NULL,
`gpa` float,
`active_days_within_30` int ,
`question_cnt` int ,
`answer_cnt` int
);
CREATE TABLE `question_practice_detail` (
`id` int NOT NULL,
`device_id` int NOT NULL,
`question_id`int NOT NULL,
`result` varchar(32) NOT NULL,
`date` date NOT NULL
);
CREATE TABLE `question_detail` (
`id` int NOT NULL,
`question_id`int NOT NULL,
`difficult_level` varchar(32) NOT NULL
);
INSERT INTO user_profile VALUES(1,2138,'male',21,'北京大学',3.4,7,2,12);
INSERT INTO user_profile VALUES(2,3214,'male',null,'复旦大学',4.0,15,5,25);
INSERT INTO user_profile VALUES(3,6543,'female',20,'北京大学',3.2,12,3,30);
INSERT INTO user_profile VALUES(4,2315,'female',23,'浙江大学',3.6,5,1,2);
INSERT INTO user_profile VALUES(5,5432,'male',25,'山东大学',3.8,20,15,70);
INSERT INTO user_profile VALUES(6,2131,'male',28,'山东大学',3.3,15,7,13);
INSERT INTO user_profile VALUES(7,4321,'male',28,'复旦大学',3.6,9,6,52);
INSERT INTO question_practice_detail VALUES(1,2138,111,'wrong','2021-05-03');
INSERT INTO question_practice_detail VALUES(2,3214,112,'wrong','2021-05-09');
INSERT INTO question_practice_detail VALUES(3,3214,113,'wrong','2021-06-15');
INSERT INTO question_practice_detail VALUES(4,6543,111,'right','2021-08-13');
INSERT INTO question_practice_detail VALUES(5,2315,115,'right','2021-08-13');
INSERT INTO question_practice_detail VALUES(6,2315,116,'right','2021-08-14');
INSERT INTO question_practice_detail VALUES(7,2315,117,'wrong','2021-08-15');
INSERT INTO question_practice_detail VALUES(8,3214,112,'wrong','2021-05-09');
INSERT INTO question_practice_detail VALUES(9,3214,113,'wrong','2021-08-15');
INSERT INTO question_practice_detail VALUES(10,6543,111,'right','2021-08-13');
INSERT INTO question_practice_detail VALUES(11,2315,115,'right','2021-08-13');
INSERT INTO question_practice_detail VALUES(12,2315,116,'right','2021-08-14');
INSERT INTO question_practice_detail VALUES(13,2315,117,'wrong','2021-08-15');
INSERT INTO question_practice_detail VALUES(14,3214,112,'wrong','2021-08-16');
INSERT INTO question_practice_detail VALUES(15,3214,113,'wrong','2021-08-18');
INSERT INTO question_practice_detail VALUES(16,6543,111,'right','2021-08-13');
INSERT INTO question_detail VALUES(1,111,'hard');
INSERT INTO question_detail VALUES(2,112,'medium');
INSERT INTO question_detail VALUES(3,113,'easy');
INSERT INTO question_detail VALUES(4,115,'easy');
INSERT INTO question_detail VALUES(5,116,'medium');
INSERT INTO question_detail VALUES(6,117,'easy');
-- 正确率:avg(正确算1/全部)
select difficult_level, round(avg(if(result='right',1,0)),4) correct_rate
from question_practice_detail qpd
join question_detail qd on qpd.question_id =qd.question_id
join user_profile u on qpd.device_id =u.device_id
where u.university='浙江大学'
group by difficult_level
order by correct_rate asc
-- 正确率:正确的次数/全部次数* 100%
-- count 会忽略null值
select difficult_level, round(count(if(result='right',1,null))/count(*),4) correct_rate
from question_practice_detail qpd
join question_detail qd on qpd.question_id =qd.question_id
join user_profile u on qpd.device_id =u.device_id
where u.university='浙江大学'
group by difficult_level
order by correct_rate asc
-- 也可以用sum
select difficult_level, round(sum(if(result='right',1,0))/count(*),4) correct_rate
from question_practice_detail qpd
join question_detail qd on qpd.question_id =qd.question_id
join user_profile u on qpd.device_id =u.device_id
where u.university='浙江大学'
group by difficult_level
order by correct_rate asc
drop table if exists `user_profile`;
drop table if exists `question_practice_detail`;
drop table if exists `question_detail`;
CREATE TABLE `user_profile` (
`id` int NOT NULL,
`device_id` int NOT NULL,
`gender` varchar(14) NOT NULL,
`age` int ,
`university` varchar(32) NOT NULL,
`gpa` float,
`active_days_within_30` int ,
`question_cnt` int ,
`answer_cnt` int
);
CREATE TABLE `question_practice_detail` (
`id` int NOT NULL,
`device_id` int NOT NULL,
`question_id`int NOT NULL,
`result` varchar(32) NOT NULL,
`date` date NOT NULL
);
CREATE TABLE `question_detail` (
`id` int NOT NULL,
`question_id`int NOT NULL,
`difficult_level` varchar(32) NOT NULL
);
INSERT INTO user_profile VALUES(1,2138,'male',21,'北京大学',3.4,7,2,12);
INSERT INTO user_profile VALUES(2,3214,'male',null,'复旦大学',4.0,15,5,25);
INSERT INTO user_profile VALUES(3,6543,'female',20,'北京大学',3.2,12,3,30);
INSERT INTO user_profile VALUES(4,2315,'female',23,'浙江大学',3.6,5,1,2);
INSERT INTO user_profile VALUES(5,5432,'male',25,'山东大学',3.8,20,15,70);
INSERT INTO user_profile VALUES(6,2131,'male',28,'山东大学',3.3,15,7,13);
INSERT INTO user_profile VALUES(7,4321,'male',28,'复旦大学',3.6,9,6,52);
INSERT INTO question_practice_detail VALUES(1,2138,111,'wrong','2021-05-03');
INSERT INTO question_practice_detail VALUES(2,3214,112,'wrong','2021-05-09');
INSERT INTO question_practice_detail VALUES(3,3214,113,'wrong','2021-06-15');
INSERT INTO question_practice_detail VALUES(4,6543,111,'right','2021-08-13');
INSERT INTO question_practice_detail VALUES(5,2315,115,'right','2021-08-13');
INSERT INTO question_practice_detail VALUES(6,2315,116,'right','2021-08-14');
INSERT INTO question_practice_detail VALUES(7,2315,117,'wrong','2021-08-15');
INSERT INTO question_practice_detail VALUES(8,3214,112,'wrong','2021-05-09');
INSERT INTO question_practice_detail VALUES(9,3214,113,'wrong','2021-08-15');
INSERT INTO question_practice_detail VALUES(10,6543,111,'right','2021-08-13');
INSERT INTO question_practice_detail VALUES(11,2315,115,'right','2021-08-13');
INSERT INTO question_practice_detail VALUES(12,2315,116,'right','2021-08-14');
INSERT INTO question_practice_detail VALUES(13,2315,117,'wrong','2021-08-15');
INSERT INTO question_practice_detail VALUES(14,3214,112,'wrong','2021-08-16');
INSERT INTO question_practice_detail VALUES(15,3214,113,'wrong','2021-08-18');
INSERT INTO question_practice_detail VALUES(16,6543,111,'right','2021-08-13');
INSERT INTO question_detail VALUES(1,111,'hard');
INSERT INTO question_detail VALUES(2,112,'medium');
INSERT INTO question_detail VALUES(3,113,'easy');
INSERT INTO question_detail VALUES(4,115,'easy');
INSERT INTO question_detail VALUES(5,116,'medium');
INSERT INTO question_detail VALUES(6,117,'easy');
-- 复旦用户:以用户为准一个都不能漏
-- 8月:如果用在where中,会将8月没有进行答题的用户过滤掉,不符合提议,所以8月需要作为连接条件
select u.device_id,university,count(qpd.result) question_cnt, count(if(result='right',1,null)) right_question_cnt
from
user_profile u
left join question_practice_detail qpd on u.device_id =qpd.device_id and date_format(date,'%Y%m')='202108'
where u.university ='复旦大学'
group by u.device_id
-- 需要注意不要将没答题的用户漏掉了
select u.device_id,university,qpd.result question_cnt, if(result='right',1,null) right_question_cnt
from
user_profile u
left join question_practice_detail qpd on u.device_id =qpd.device_id and date_format(date,'%Y%m')='202108'
where u.university ='复旦大学'
-- 或者左外的时候,把右表空记录也取出来
select u.device_id,university,qpd.result question_cnt, if(result='right',1,null) right_question_cnt
from
user_profile u
left join question_practice_detail qpd on u.device_id =qpd.device_id
where u.university ='复旦大学' and (date_format(date,'%Y%m')='202108' or date is null)
device_id|university|question_cnt|right_question_cnt|
---------+----------+------------+------------------+
3214|复旦大学 |wrong | |
3214|复旦大学 |wrong | |
3214|复旦大学 |wrong | |
4321|复旦大学 | | |
drop table if exists user_profile;
CREATE TABLE `user_profile` (
`id` int NOT NULL,
`device_id` int NOT NULL,
`gender` varchar(14) NOT NULL,
`age` int ,
`university` varchar(32) NOT NULL,
`gpa` float,
`active_days_within_30` int ,
`question_cnt` int ,
`answer_cnt` int
);
INSERT INTO user_profile VALUES(1,2138,'male',21,'北京大学',3.4,7,2,12);
INSERT INTO user_profile VALUES(2,3214,'male',null,'复旦大学',4.0,15,5,25);
INSERT INTO user_profile VALUES(3,6543,'female',20,'北京大学',3.2,12,3,30);
INSERT INTO user_profile VALUES(4,2315,'female',23,'浙江大学',3.6,5,1,2);
INSERT INTO user_profile VALUES(5,5432,'male',25,'山东大学',3.8,20,15,70);
INSERT INTO user_profile VALUES(6,2131,'male',28,'山东大学',3.3,15,7,13);
INSERT INTO user_profile VALUES(7,4321,'male',28,'复旦大学',3.6,9,6,52);
-- 每个topN
select device_id, university, round(gpa,4 ) gpa from (
select device_id, university, gpa,
rank() over(partition by university order by gpa asc) rk
from user_profile
) tmp
where rk=1
order by university asc
-- 1.将每个学生的gpa和最小的ga比较,
-- 2.将外层的device_id所在university放入子查询中,
-- 3.意味着每个学生都都要查询他所在学校的最小值
-- 4.如果等于最小值,返回值
select device_id, university, gpa
from user_profile u
where u.gpa=(
select min(gpa) from user_profile u2
where u2.university=u.university
)
order by university asc
-- 1.构造一张只有每个学校最低分的虚表
-- 2.从学生全表中和虚表关联,连接条件是学校和最低分
select device_id, u.university, gpa
from user_profile u
join (
select university,min(gpa) min_gpa
from user_profile
group by university
) u2 on u.university=u2.university and u.gpa=u2.min_gpa
order by university asc
drop table if exists user_submit;
CREATE TABLE `user_submit` (
`id` int NOT NULL,
`device_id` int NOT NULL,
`profile` varchar(100) NOT NULL,
`blog_url` varchar(100) NOT NULL
);
INSERT INTO user_submit VALUES(1,2138,'180cm,75kg,27,male','http:/url/bisdgboy777');
INSERT INTO user_submit VALUES(1,3214,'165cm,45kg,26,female','http:/url/dkittycc');
INSERT INTO user_submit VALUES(1,6543,'178cm,65kg,25,male','http:/url/tigaer');
INSERT INTO user_submit VALUES(1,4321,'171cm,55kg,23,female','http:/url/uhsksd');
INSERT INTO user_submit VALUES(1,2131,'168cm,45kg,22,female','http:/url/sysdney');
1、LOCATE(substr , str ):返回子串 substr 在字符串 str 中第一次出现的位置,如果字符substr在字符串str中不存在,则返回0;
2、POSITION(substr IN str ):返回子串 substr 在字符串 str 中第一次出现的位置,如果字符substr在字符串str中不存在,与LOCATE函数作用相同;
3、LEFT(str, length):从左边开始截取str,length是截取的长度;
4、RIGHT(str, length):从右边开始截取str,length是截取的长度;
5、SUBSTRING_INDEX(str ,substr ,n):返回字符substr在str中第n次出现位置之前的字符串;
6、SUBSTRING(str ,n ,m):返回字符串str从第n个字符截取到第m个字符;
7、REPLACE(str, n, m):将字符串str中的n字符替换成m字符;
8、LENGTH(str):计算字符串str的长度。
-- 通过下标取数据
select device_id,substring_index(blog_url,'/',-1) user_name
from user_submit
-- 截取从pos位置开始到最后的所有str字符串
-- SUBSTR (str, pos, len)
select device_id,substr(blog_url,11) user_name
from user_submit
-- 替换取
select device_id,replace(blog_url,'http:/url/','') user_name
from user_submit
-- 通过裁剪取:trim('被裁减的内容' from 字段)
select device_id ,trim('http:/url/' from blog_url) as user_name
from user_submit
drop table if exists `user_profile`;
drop table if exists `question_practice_detail`;
drop table if exists `question_detail`;
CREATE TABLE `user_profile` (
`id` int NOT NULL,
`device_id` int NOT NULL,
`gender` varchar(14) NOT NULL,
`age` int ,
`university` varchar(32) NOT NULL,
`gpa` float,
`active_days_within_30` int ,
`question_cnt` int ,
`answer_cnt` int
);
CREATE TABLE `question_practice_detail` (
`id` int NOT NULL,
`device_id` int NOT NULL,
`question_id`int NOT NULL,
`result` varchar(32) NOT NULL,
`date` date NOT NULL
);
CREATE TABLE `question_detail` (
`id` int NOT NULL,
`question_id`int NOT NULL,
`difficult_level` varchar(32) NOT NULL
);
INSERT INTO user_profile VALUES(1,2138,'male',21,'北京大学',3.4,7,2,12);
INSERT INTO user_profile VALUES(2,3214,'male',null,'复旦大学',4.0,15,5,25);
INSERT INTO user_profile VALUES(3,6543,'female',20,'北京大学',3.2,12,3,30);
INSERT INTO user_profile VALUES(4,2315,'female',23,'浙江大学',3.6,5,1,2);
INSERT INTO user_profile VALUES(5,5432,'male',25,'山东大学',3.8,20,15,70);
INSERT INTO user_profile VALUES(6,2131,'male',28,'山东大学',3.3,15,7,13);
INSERT INTO user_profile VALUES(7,4321,'male',28,'复旦大学',3.6,9,6,52);
INSERT INTO question_practice_detail VALUES(1,2138,111,'wrong','2021-05-03');
INSERT INTO question_practice_detail VALUES(2,3214,112,'wrong','2021-05-09');
INSERT INTO question_practice_detail VALUES(3,3214,113,'wrong','2021-06-15');
INSERT INTO question_practice_detail VALUES(4,6543,111,'right','2021-08-13');
INSERT INTO question_practice_detail VALUES(5,2315,115,'right','2021-08-13');
INSERT INTO question_practice_detail VALUES(6,2315,116,'right','2021-08-14');
INSERT INTO question_practice_detail VALUES(7,2315,117,'wrong','2021-08-15');
INSERT INTO question_practice_detail VALUES(8,3214,112,'wrong','2021-05-09');
INSERT INTO question_practice_detail VALUES(9,3214,113,'wrong','2021-08-15');
INSERT INTO question_practice_detail VALUES(10,6543,111,'right','2021-08-13');
INSERT INTO question_practice_detail VALUES(11,2315,115,'right','2021-08-13');
INSERT INTO question_practice_detail VALUES(12,2315,116,'right','2021-08-14');
INSERT INTO question_practice_detail VALUES(13,2315,117,'wrong','2021-08-15');
INSERT INTO question_practice_detail VALUES(14,3214,112,'wrong','2021-08-16');
INSERT INTO question_practice_detail VALUES(15,3214,113,'wrong','2021-08-18');
INSERT INTO question_practice_detail VALUES(16,6543,111,'right','2021-08-13');
INSERT INTO question_detail VALUES(1,111,'hard');
INSERT INTO question_detail VALUES(2,112,'medium');
INSERT INTO question_detail VALUES(3,113,'easy');
INSERT INTO question_detail VALUES(4,115,'easy');
INSERT INTO question_detail VALUES(5,116,'medium');
INSERT INTO question_detail VALUES(6,117,'easy');
select count(if(datediff(date2,date1)=1,1,null))/count(*)
from (
select device_id,date date1,
lead(date,1) over (partition by device_id order by date) date2
from
(select distinct device_id,date from question_practice_detail) tmp
) t
select count(datediff)/count(*)
from (
select device_id,date,
if(datediff(lead(date,1) over (partition by device_id order by date),date)=1,1,null) datediff
from
(select distinct device_id,date from question_practice_detail) tmp
) t
select avg(if(date2,1,0))
from (
select device_id,date,
if(datediff(lead(date,1) over (partition by device_id order by date),date)=1,1,null) date2
from
(select distinct device_id,date from question_practice_detail) tmp
) t
select device_id,date,
if(datediff(date,lag(date,1) over (partition by device_id order by date))=1,1,null) date2
from
(select distinct device_id,date from question_practice_detail) tmp
-- 左外连多加一天,右表有值表示隔天又登录,null表示隔天没登录
-- 用data_add/data_sub
select count(date2)/count(*)
-- select avg(if(date2,1,0))
from (
select distinct q1.device_id,q2.date date2,q1.date date1
from
question_practice_detail q1
left join question_practice_detail q2 on q1.device_id=q2.device_id and date_add(q1.date,interval 1 day)=q2.date
) t
-- 也可以用datediff
select count(date2)/count(*)
-- select avg(if(date2,1,0))
from (
select distinct q1.device_id,q2.date date2,q1.date date1
from
question_practice_detail q1
left join question_practice_detail q2 on q1.device_id=q2.device_id and datediff(q1.date,q2.date)=1
) t
以下为SQL进阶挑战题目
drop table if exists examination_info;
CREATE TABLE examination_info (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
exam_id int UNIQUE NOT NULL COMMENT '试卷ID',
tag varchar(32) COMMENT '类别标签',
difficulty varchar(8) COMMENT '难度',
duration int NOT NULL COMMENT '时长',
release_time datetime COMMENT '发布时间'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
drop table if exists exam_record;
CREATE TABLE exam_record (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int NOT NULL COMMENT '用户ID',
exam_id int NOT NULL COMMENT '试卷ID',
start_time datetime NOT NULL COMMENT '开始时间',
submit_time datetime COMMENT '提交时间',
score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
INSERT INTO examination_info(exam_id,tag,difficulty,duration,release_time) VALUES
(9001, 'SQL', 'hard', 60, '2020-01-01 10:00:00'),
(9002, '算法', 'medium', 80, '2020-08-02 10:00:00');
INSERT INTO exam_record(uid,exam_id,start_time,submit_time,score) VALUES
(1001, 9001, '2020-01-02 09:01:01', '2020-01-02 09:21:01', 80),
(1001, 9001, '2021-05-02 10:01:01', '2021-05-02 10:30:01', 81),
(1001, 9001, '2021-06-02 19:01:01', '2021-06-02 19:31:01', 84),
(1001, 9002, '2021-09-05 19:01:01', '2021-09-05 19:40:01', 89),
(1001, 9001, '2021-09-02 12:01:01', null, null),
(1001, 9002, '2021-09-01 12:01:01', null, null),
(1002, 9002, '2021-02-02 19:01:01', '2021-02-02 19:30:01', 87),
(1002, 9001, '2021-05-05 18:01:01', '2021-05-05 18:59:02', 90),
(1003, 9001, '2021-02-06 12:01:01', null, null),
(1003, 9001, '2021-09-07 10:01:01', '2021-09-07 10:31:01', 50);
-- 去掉一个最高分,去掉一个最低分,去掉null,求平均值
with tmp as (
select tag,difficulty,er.score
from exam_record er
join examination_info ei on er.exam_id=ei.exam_id
where ei.tag='SQL'
and ei.difficulty ='hard'
and score is not null )
select tag,difficulty,round((sum(score)-min(score)-max(score))/(count(*)-2),1) from tmp
group by tag,difficulty
-- min/max + 开窗
select tag,difficulty,round((sum(score) - max(max_score)-min(min_score))/(count(*)-2),1) from (
select tag,difficulty,er.score,
max(score) over(partition by tag,difficulty order by score) max_score,
min(score) over(partition by tag,difficulty order by score) min_score
from exam_record er
join examination_info ei on er.exam_id=ei.exam_id
where ei.tag='SQL'
and ei.difficulty ='hard'
and score is not null )t
group by tag,difficulty
-- 没说按照那一个进行分组或者分区,就是全表求最值
select tag,difficulty,round((sum(score) - max(score)-min(score))/(count(*)-2),1)
from exam_record er
join examination_info ei on er.exam_id=ei.exam_id
where ei.tag='SQL'
and ei.difficulty ='hard'
and score is not null
-- 条件中放min/max
-- not或者不等中可能会过滤掉相同的极值
select tag,difficulty,round(avg(score),1)
from exam_record er
join examination_info ei on er.exam_id=ei.exam_id
where ei.tag='SQL'
and ei.difficulty ='hard'
and score not in (select max(score) from exam_record)
and score not in (select min(score) from exam_record)
-- rank + 开窗
select tag,difficulty,round(avg(score),1) from (
select tag,difficulty,er.score,
rank() over(partition by tag,difficulty order by score desc) rk_max,
rank() over(partition by tag,difficulty order by score asc) rk_min
from exam_record er
join examination_info ei on er.exam_id=ei.exam_id
where ei.tag='SQL'
and ei.difficulty ='hard'
and score is not null )t where rk_max!=1 and rk_min!=1
drop table if exists exam_record;
CREATE TABLE exam_record (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int NOT NULL COMMENT '用户ID',
exam_id int NOT NULL COMMENT '试卷ID',
start_time datetime NOT NULL COMMENT '开始时间',
submit_time datetime COMMENT '提交时间',
score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
INSERT INTO exam_record(uid,exam_id,start_time,submit_time,score) VALUES
(1001, 9001, '2020-01-02 09:01:01', '2020-01-02 09:21:01', 80),
(1001, 9001, '2021-05-02 10:01:01', '2021-05-02 10:30:01', 81),
(1001, 9001, '2021-06-02 19:01:01', '2021-06-02 19:31:01', 84),
(1001, 9002, '2021-09-05 19:01:01', '2021-09-05 19:40:01', 89),
(1001, 9001, '2021-09-02 12:01:01', null, null),
(1001, 9002, '2021-09-01 12:01:01', null, null),
(1002, 9002, '2021-02-02 19:01:01', '2021-02-02 19:30:01', 87),
(1002, 9001, '2021-05-05 18:01:01', '2021-05-05 18:59:02', 90),
(1003, 9001, '2021-02-06 12:01:01', null, null),
(1003, 9001, '2021-09-07 10:01:01', '2021-09-07 10:31:01', 89),
(1004, 9001, '2021-09-06 12:01:01', null, null);
- count(distinct 字段 and 字段 is not null)
SELECT
COUNT(start_time) as total_pv, #有开始作答时间可视为一次作答
COUNT(submit_time) as complete_pv,#有交卷时间可视为完成一次作答
count(distinct exam_id and score is not null)
as complete_exam_cnt#将试卷去重,同时将筛选完成的试卷
from exam_record;
drop table if exists examination_info;
CREATE TABLE examination_info (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
exam_id int UNIQUE NOT NULL COMMENT '试卷ID',
tag varchar(32) COMMENT '类别标签',
difficulty varchar(8) COMMENT '难度',
duration int NOT NULL COMMENT '时长',
release_time datetime COMMENT '发布时间'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
drop table if exists exam_record;
CREATE TABLE exam_record (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int NOT NULL COMMENT '用户ID',
exam_id int NOT NULL COMMENT '试卷ID',
start_time datetime NOT NULL COMMENT '开始时间',
submit_time datetime COMMENT '提交时间',
score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
INSERT INTO examination_info(exam_id,tag,difficulty,duration,release_time) VALUES
(9001, 'SQL', 'hard', 60, '2020-01-01 10:00:00'),
(9002, 'SQL', 'easy', 60, '2020-02-01 10:00:00'),
(9003, '算法', 'medium', 80, '2020-08-02 10:00:00');
INSERT INTO exam_record(uid,exam_id,start_time,submit_time,score) VALUES
(1001, 9001, '2020-01-02 09:01:01', '2020-01-02 09:21:01', 80),
(1002, 9001, '2021-09-05 19:01:01', '2021-09-05 19:40:01', 89),
(1002, 9002, '2021-09-02 12:01:01', null, null),
(1002, 9003, '2021-09-01 12:01:01', null, null),
(1002, 9001, '2021-02-02 19:01:01', '2021-02-02 19:30:01', 87),
(1002, 9002, '2021-05-05 18:01:01', '2021-05-05 18:59:02', 90),
(1003, 9002, '2021-02-06 12:01:01', null, null),
(1003, 9003, '2021-09-07 10:01:01', '2021-09-07 10:31:01', 86),
(1004, 9003, '2021-09-06 12:01:01', null, null);
select min(score) from exam_record er
join examination_info ei on er.exam_id =ei.exam_id
where
score >=
(
select avg(score)
from exam_record er
left join examination_info ei on er.exam_id =ei.exam_id where tag='SQL'
)
and tag='SQL'
with e as(
select er.score
from exam_record er
left join examination_info ei
on er.exam_id=ei.exam_id
where ei.tag='SQL'
and er.score is not null
)
select
min(score) min_score_over_avg
from e
where score>=(select avg(score) from e)
select min(score) from (
select er.score,
avg(score) over () avg_score
from exam_record er
left join examination_info ei
on er.exam_id=ei.exam_id
where ei.tag='SQL'
and er.score is not null
)t
where score >avg_score
drop table if exists exam_record;
CREATE TABLE exam_record (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int NOT NULL COMMENT '用户ID',
exam_id int NOT NULL COMMENT '试卷ID',
start_time datetime NOT NULL COMMENT '开始时间',
submit_time datetime COMMENT '提交时间',
score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
INSERT INTO exam_record(uid,exam_id,start_time,submit_time,score) VALUES
(1001, 9001, '2021-07-02 09:01:01', '2021-07-02 09:21:01', 80),
(1002, 9001, '2021-09-05 19:01:01', '2021-09-05 19:40:01', 81),
(1002, 9002, '2021-09-02 12:01:01', null, null),
(1002, 9003, '2021-09-01 12:01:01', null, null),
(1002, 9001, '2021-07-02 19:01:01', '2021-07-02 19:30:01', 82),
(1002, 9002, '2021-07-05 18:01:01', '2021-07-05 18:59:02', 90),
(1003, 9002, '2021-07-06 12:01:01', null, null),
(1003, 9003, '2021-09-07 10:01:01', '2021-09-07 10:31:01', 86),
(1004, 9003, '2021-09-06 12:01:01', null, null),
(1002, 9003, '2021-09-01 12:01:01', '2021-09-01 12:31:01', 81),
(1005, 9001, '2021-09-01 12:01:01', '2021-09-01 12:31:01', 88),
(1006, 9002, '2021-09-02 12:11:01', '2021-09-02 12:31:01', 89);
select date_format(submit_time,'%Y%m') month,
-- 每用户每天需要唯一
round(count(distinct uid,date_format(submit_time,'%Y%m%d')) /count(distinct uid),2),
count(distinct uid) mau
from exam_record
where year(submit_time)='2021'
group by month
select date_format(day,'%Y%m') month, round(count(day)/count(distinct uid),2),count(distinct uid)
from(
-- 先过滤好每天的每用户
select distinct date_format(start_time,'%Y%m%d') day, uid
from exam_record
where year(submit_time)='2021'
)t
group by month
drop table if exists practice_record;
CREATE TABLE practice_record (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int NOT NULL COMMENT '用户ID',
question_id int NOT NULL COMMENT '题目ID',
submit_time datetime COMMENT '提交时间',
score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
INSERT INTO practice_record(uid,question_id,submit_time,score) VALUES
(1001, 8001, '2021-08-02 11:41:01', 60),
(1002, 8001, '2021-09-02 19:30:01', 50),
(1002, 8001, '2021-09-02 19:20:01', 70),
(1002, 8002, '2021-09-02 19:38:01', 70),
(1003, 8002, '2021-08-01 19:38:01', 80);
-- coaleasce 顺序判断返回第一个不为null的值
select coalesce(month,'2021汇总'),month_q_cnt,avg_day_q_cnt from (
select DATE_FORMAT(submit_time,"%Y%m") month,
count(question_id) month_q_cnt,
-- 必须多套一层,下面这个无法返回别名
-- COALESCE (DATE_FORMAT(submit_time, "%Y%m"),"2021汇总") AS submit_month,
round(count(question_id)/max(right(last_day(submit_time),2)),3) avg_day_q_cnt
from practice_record
where year(submit_time)='2021'
group by month
with rollup
) t
-- 当月的最后一天日期 dayofmonth(last_day(now()))
-- 或者 day(last_day(now())) 同理还有year month time函数
-- MySQL提供了 group by with rollup 函数进行group by 字段的汇总,但是与order by 互斥,不能同时用
select last_day(now()),dayofmonth(now()),dayofmonth(last_day(now()));
+-----------------+-------------------+-----------------------------+
| last_day(now()) | dayofmonth(now()) | dayofmonth(last_day(now())) |
+-----------------+-------------------+-----------------------------+
| 2022-03-31 | 19 | 31 |
+-----------------+-----
drop table if exists examination_info;
CREATE TABLE examination_info (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
exam_id int UNIQUE NOT NULL COMMENT '试卷ID',
tag varchar(32) COMMENT '类别标签',
difficulty varchar(8) COMMENT '难度',
duration int NOT NULL COMMENT '时长',
release_time datetime COMMENT '发布时间'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
drop table if exists exam_record;
CREATE TABLE exam_record (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int NOT NULL COMMENT '用户ID',
exam_id int NOT NULL COMMENT '试卷ID',
start_time datetime NOT NULL COMMENT '开始时间',
submit_time datetime COMMENT '提交时间',
score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
INSERT INTO examination_info(exam_id,tag,difficulty,duration,release_time) VALUES
(9001, 'SQL', 'hard', 60, '2020-01-01 10:00:00'),
(9002, 'SQL', 'easy', 60, '2020-02-01 10:00:00'),
(9003, '算法', 'medium', 80, '2020-08-02 10:00:00');
INSERT INTO exam_record(uid,exam_id,start_time,submit_time,score) VALUES
(1001, 9001, '2021-07-02 09:01:01', '2021-07-02 09:21:01', 80),
(1002, 9001, '2021-09-05 19:01:01', '2021-09-05 19:40:01', 81),
(1002, 9002, '2021-09-02 12:01:01', null, null),
(1002, 9003, '2021-09-01 12:01:01', null, null),
(1002, 9001, '2021-07-02 19:01:01', '2021-07-02 19:30:01', 82),
(1002, 9002, '2021-07-05 18:01:01', '2021-07-05 18:59:02', 90),
(1003, 9002, '2021-07-06 12:01:01', null, null),
(1003, 9003, '2021-09-07 10:01:01', '2021-09-07 10:31:01', 86),
(1004, 9003, '2021-09-06 12:01:01', null, null),
(1002, 9003, '2021-09-01 12:01:01', '2021-09-01 12:31:01', 81),
(1005, 9001, '2021-09-01 12:01:01', '2021-09-01 12:31:01', 88),
(1005, 9002, '2021-09-01 12:01:01', '2021-09-01 12:31:01', 88),
(1006, 9002, '2021-09-02 12:11:01', '2021-09-02 12:31:01', 89);
select
uid,
-- 不能用上score,需要submit字段?
-- count(if(score,null,1)) incomplete_cnt,
-- count(if(score,1,null)) complete_cnt,
count(if(submit_time,null,1)) incomplete_cnt,
count(if(submit_time,1,null)) complete_cnt,
-- group_concat([distinct] 要连接的字段 [order by 排序字段 asc/desc ] [separator '分隔符'])
group_concat(distinct concat_ws(':', date(start_time), tag) SEPARATOR ';') as detail
from exam_record er
join examination_info ei on er.exam_id =ei.exam_id
where year(start_time)='2021'
group by uid
having complete_cnt >= 1 and incomplete_cnt < 5 and incomplete_cnt > 1
order by incomplete_cnt DESC
select
uid,
-- 不能用上score,需要submit字段?
-- count(if(score,null,1)) incomplete_cnt,
-- count(if(score,1,null)) complete_cnt,
count(if(submit_time,null,1)) incomplete_cnt,
count(if(submit_time,1,null)) complete_cnt,
-- group_concat([distinct] 要连接的字段 [order by 排序字段 asc/desc ] [separator '分隔符'])
group_concat(distinct concat( date(start_time), ':',tag) SEPARATOR ';') as detail
from exam_record er
join examination_info ei on er.exam_id =ei.exam_id
where year(start_time)='2021'
group by uid
having complete_cnt >= 1 and incomplete_cnt < 5 and incomplete_cnt > 1
order by incomplete_cnt DESC
drop table if exists examination_info,exam_record;
CREATE TABLE examination_info (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
exam_id int UNIQUE NOT NULL COMMENT '试卷ID',
tag varchar(32) COMMENT '类别标签',
difficulty varchar(8) COMMENT '难度',
duration int NOT NULL COMMENT '时长',
release_time datetime COMMENT '发布时间'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE TABLE exam_record (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int NOT NULL COMMENT '用户ID',
exam_id int NOT NULL COMMENT '试卷ID',
start_time datetime NOT NULL COMMENT '开始时间',
submit_time datetime COMMENT '提交时间',
score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
INSERT INTO examination_info(exam_id,tag,difficulty,duration,release_time) VALUES
(9001, 'SQL', 'hard', 60, '2020-01-01 10:00:00'),
(9002, 'C++', 'easy', 60, '2020-02-01 10:00:00'),
(9003, '算法', 'medium', 80, '2020-08-02 10:00:00');
INSERT INTO exam_record(uid,exam_id,start_time,submit_time,score) VALUES
(1001, 9001, '2021-07-02 09:01:01', null, null),
(1002, 9003, '2021-09-01 12:01:01', '2021-09-01 12:21:01', 60),
(1002, 9002, '2021-09-02 12:01:01', '2021-09-02 12:31:01', 70),
(1002, 9001, '2021-09-05 19:01:01', '2021-09-05 19:40:01', 81),
(1002, 9002, '2021-07-06 12:01:01', null, null),
(1003, 9003, '2021-09-07 10:01:01', '2021-09-07 10:31:01', 86),
(1003, 9003, '2021-09-08 12:01:01', '2021-09-08 12:11:01', 40),
(1003, 9001, '2021-09-08 13:01:01', null, null),
(1003, 9002, '2021-09-08 14:01:01', null, null),
(1003, 9003, '2021-09-08 15:01:01', null, null),
(1005, 9001, '2021-09-01 12:01:01', '2021-09-01 12:31:01', 88),
(1005, 9002, '2021-09-01 12:01:01', '2021-09-01 12:31:01', 88),
(1005, 9002, '2021-09-02 12:11:01', '2021-09-02 12:31:01', 89);
select
(select tag from examination_info where exam_id=er.exam_id limit 1 ) tag,count(exam_id) cnt
from exam_record er
where uid in(
select uid from (
select uid,date_format(submit_time,'%Y%m') month, count(exam_id) cnt
from exam_record er
where submit_time is not null
group by uid,month having cnt >=3
) tmp
)
group by exam_ida
order by cnt desc
-- 去掉标量子查询
select
tag,count(er.exam_id) cnt
from exam_record er
join examination_info ei on ei.exam_id=er.exam_id
where uid in(
select uid from (
select uid,date_format(submit_time,'%Y%m') month, count(exam_id) cnt
from exam_record er
where submit_time is not null
group by uid,month having cnt >=3
) tmp
)
group by tag
order by cnt desc
-- 将子查询的次数判断放入having,减少一层嵌套
select
tag,count(er.exam_id) cnt
from exam_record er
join examination_info ei on ei.exam_id=er.exam_id
where uid in(
select uid
from exam_record er
where submit_time is not null
group by uid having count(exam_id)/count(distinct date_format(submit_time,'%Y%m')) >=3
)
group by tag
order by cnt desc
SQL21 试卷发布当天作答人数和平均分
drop table if exists examination_info,user_info,exam_record;
CREATE TABLE examination_info (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
exam_id int UNIQUE NOT NULL COMMENT '试卷ID',
tag varchar(32) COMMENT '类别标签',
difficulty varchar(8) COMMENT '难度',
duration int NOT NULL COMMENT '时长',
release_time datetime COMMENT '发布时间'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE TABLE user_info (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int UNIQUE NOT NULL COMMENT '用户ID',
`nick_name` varchar(64) COMMENT '昵称',
achievement int COMMENT '成就值',
level int COMMENT '用户等级',
job varchar(32) COMMENT '职业方向',
register_time datetime COMMENT '注册时间'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE TABLE exam_record (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int NOT NULL COMMENT '用户ID',
exam_id int NOT NULL COMMENT '试卷ID',
start_time datetime NOT NULL COMMENT '开始时间',
submit_time datetime COMMENT '提交时间',
score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
INSERT INTO user_info(uid,`nick_name`,achievement,level,job,register_time) VALUES
(1001, '牛客1号', 3100, 7, '算法', '2020-01-01 10:00:00'),
(1002, '牛客2号', 2100, 6, '算法', '2020-01-01 10:00:00'),
(1003, '牛客3号', 1500, 5, '算法', '2020-01-01 10:00:00'),
(1004, '牛客4号', 1100, 4, '算法', '2020-01-01 10:00:00'),
(1005, '牛客5号', 1600, 6, 'C++', '2020-01-01 10:00:00'),
(1006, '牛客6号', 3000, 6, 'C++', '2020-01-01 10:00:00');
INSERT INTO examination_info(exam_id,tag,difficulty,duration,release_time) VALUES
(9001, 'SQL', 'hard', 60, '2021-09-01 06:00:00'),
(9002, 'C++', 'easy', 60, '2020-02-01 10:00:00'),
(9003, '算法', 'medium', 80, '2020-08-02 10:00:00');
INSERT INTO exam_record(uid,exam_id,start_time,submit_time,score) VALUES
(1001, 9001, '2021-09-01 09:01:01', '2021-09-01 09:41:01', 70),
(1002, 9003, '2021-09-01 12:01:01', '2021-09-01 12:21:01', 60),
(1002, 9002, '2021-09-02 12:01:01', '2021-09-02 12:31:01', 70),
(1002, 9001, '2021-09-01 19:01:01', '2021-09-01 19:40:01', 80),
(1002, 9003, '2021-08-01 12:01:01', '2021-08-01 12:21:01', 60),
(1002, 9002, '2021-08-02 12:01:01', '2021-08-02 12:31:01', 70),
(1002, 9001, '2021-09-01 19:01:01', '2021-09-01 19:40:01', 85),
(1002, 9002, '2021-07-06 12:01:01', null, null),
(1003, 9003, '2021-09-07 10:01:01', '2021-09-07 10:31:01', 86),
(1003, 9003, '2021-09-08 12:01:01', '2021-09-08 12:11:01', 40),
(1003, 9001, '2021-09-01 13:01:01', '2021-09-01 13:41:01', 70),
(1003, 9002, '2021-09-08 14:01:01', null, null),
(1003, 9003, '2021-09-08 15:01:01', null, null),
(1005, 9001, '2021-09-01 12:01:01', '2021-09-01 12:31:01', 90),
(1005, 9002, '2021-09-01 12:01:01', '2021-09-01 12:31:01', 88),
(1005, 9002, '2021-09-02 12:11:01', '2021-09-02 12:31:01', 89);
select er.exam_id,count(distinct er.uid) uv,round(avg(er.score),1) avg_score
from exam_record er
join user_info u on er.uid=u.uid
join examination_info ei on ei.exam_id= er.exam_id
where u.level >5
AND tag='SQL'
and date(ei.release_time)=date(er.submit_time)
group by exam_id
order by uv desc,avg_score asc
SQL24 分别满足两个活动的人
drop table if exists examination_info;
CREATE TABLE examination_info (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
exam_id int UNIQUE NOT NULL COMMENT '试卷ID',
tag varchar(32) COMMENT '类别标签',
difficulty varchar(8) COMMENT '难度',
duration int NOT NULL COMMENT '时长',
release_time datetime COMMENT '发布时间'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
drop table if exists exam_record;
CREATE TABLE exam_record (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int NOT NULL COMMENT '用户ID',
exam_id int NOT NULL COMMENT '试卷ID',
start_time datetime NOT NULL COMMENT '开始时间',
submit_time datetime COMMENT '提交时间',
score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
INSERT INTO examination_info(exam_id,tag,difficulty,duration,release_time) VALUES
(9001, 'SQL', 'hard', 60, '2021-09-01 06:00:00'),
(9002, 'C++', 'hard', 60, '2021-09-01 06:00:00'),
(9003, '算法', 'medium', 80, '2021-09-01 10:00:00');
INSERT INTO exam_record(uid,exam_id,start_time,submit_time,score) VALUES
(1001, 9001, '2021-09-01 09:01:01', '2021-09-01 09:31:00', 81),
(1002, 9002, '2021-09-01 12:01:01', '2021-09-01 12:31:01', 70),
(1003, 9001, '2021-09-01 19:01:01', '2021-09-01 19:40:01', 86),
(1003, 9002, '2021-09-01 12:01:01', '2021-09-01 12:31:51', 89),
(1004, 9001, '2021-09-01 19:01:01', '2021-09-01 19:30:01', 85);
with tmp as(
select er.uid, er.exam_id,score, timestampdiff(minute, start_time, submit_time) timed ,ei.duration duration1
from exam_record er
join examination_info ei on er.exam_id =ei.exam_id
where year(er.submit_time)='2021'
)
select uid,'activity1'
from tmp
group by uid having min(score) >=85
union all
select distinct uid,'activity2'
from tmp
join examination_info ei2 on tmp.exam_id=ei2.exam_id
where timed =80
order by uid
-- 输出2021年里 所有每次试卷得分都能到85分的人
select er.uid, 'activity1' activity
from exam_record er
join examination_info ei on er.exam_id=ei.exam_id
where year(submit_time) ='2021'
group by uid,activity having min(score) >=85
union
-- 输出2021年里 至少有一次用了一半时间就完成高难度试卷且分数大于80的人的id和活动号
select distinct uid,activity from (
select er.uid, 'activity2' activity,ei.duration*60/2 - TIMESTAMPDIFF(second,start_time,submit_time) comp_time
from exam_record er
join examination_info ei on er.exam_id=ei.exam_id
and score >80
and difficulty = 'hard'
and year(submit_time) ='2021'
) t
where comp_time >=0
order by uid asc
SQL25 满足条件的用户的试卷完成数和题目练习数
drop table if exists examination_info,user_info,exam_record,practice_record;
CREATE TABLE examination_info (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
exam_id int UNIQUE NOT NULL COMMENT '试卷ID',
tag varchar(32) COMMENT '类别标签',
difficulty varchar(8) COMMENT '难度',
duration int NOT NULL COMMENT '时长',
release_time datetime COMMENT '发布时间'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE TABLE user_info (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int UNIQUE NOT NULL COMMENT '用户ID',
`nick_name` varchar(64) COMMENT '昵称',
achievement int COMMENT '成就值',
level int COMMENT '用户等级',
job varchar(32) COMMENT '职业方向',
register_time datetime COMMENT '注册时间'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE TABLE practice_record (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int NOT NULL COMMENT '用户ID',
question_id int NOT NULL COMMENT '题目ID',
submit_time datetime COMMENT '提交时间',
score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE TABLE exam_record (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int NOT NULL COMMENT '用户ID',
exam_id int NOT NULL COMMENT '试卷ID',
start_time datetime NOT NULL COMMENT '开始时间',
submit_time datetime COMMENT '提交时间',
score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
INSERT INTO user_info(uid,`nick_name`,achievement,level,job,register_time) VALUES
(1001, '牛客1号', 3100, 7, '算法', '2020-01-01 10:00:00'),
(1002, '牛客2号', 2300, 7, '算法', '2020-01-01 10:00:00'),
(1003, '牛客3号', 2500, 7, '算法', '2020-01-01 10:00:00'),
(1004, '牛客4号', 1200, 5, '算法', '2020-01-01 10:00:00'),
(1005, '牛客5号', 1600, 6, 'C++', '2020-01-01 10:00:00'),
(1006, '牛客6号', 2000, 6, 'C++', '2020-01-01 10:00:00');
INSERT INTO examination_info(exam_id,tag,difficulty,duration,release_time) VALUES
(9001, 'SQL', 'hard', 60, '2021-09-01 06:00:00'),
(9002, 'C++', 'hard', 60, '2021-09-01 06:00:00'),
(9003, '算法', 'medium', 80, '2021-09-01 10:00:00');
INSERT INTO practice_record(uid,question_id,submit_time,score) VALUES
(1001, 8001, '2021-08-02 11:41:01', 60),
(1002, 8001, '2021-09-02 19:30:01', 50),
(1002, 8001, '2021-09-02 19:20:01', 70),
(1002, 8002, '2021-09-02 19:38:01', 70),
(1004, 8001, '2021-08-02 19:38:01', 70),
(1004, 8002, '2021-08-02 19:48:01', 90),
(1001, 8002, '2021-08-02 19:38:01', 70),
(1004, 8002, '2021-08-02 19:48:01', 90),
(1004, 8002, '2021-08-02 19:58:01', 94),
(1004, 8003, '2021-08-02 19:38:01', 70),
(1004, 8003, '2021-08-02 19:48:01', 90),
(1004, 8003, '2021-08-01 19:38:01', 80);
INSERT INTO exam_record(uid,exam_id,start_time,submit_time,score) VALUES
(1001, 9001, '2021-09-01 09:01:01', '2021-09-01 09:31:00', 81),
(1002, 9002, '2021-09-01 12:01:01', '2021-09-01 12:31:01', 81),
(1003, 9001, '2021-09-01 19:01:01', '2021-09-01 19:40:01', 86),
(1003, 9002, '2021-09-01 12:01:01', '2021-09-01 12:31:51', 89),
(1004, 9001, '2021-09-01 19:01:01', '2021-09-01 19:30:01', 85),
(1005, 9002, '2021-09-01 12:01:01', '2021-09-01 12:31:02', 85),
(1006, 9003, '2021-09-07 10:01:01', '2021-09-07 10:21:01', 84),
(1006, 9001, '2021-09-07 10:01:01', '2021-09-07 10:21:01', 80);
-- 高难度SQL试卷得分平均值大于80并且是7级的红名大佬
-- 统计他们的2021年试卷总完成次数和题目总练习次数
-- 只保留2021年有试卷完成记录的用户
-- 1.查找用户
with tmp_u as
(
select u.uid uid,avg(er.score) score
from user_info u
join exam_record er on u.uid=er.uid
join examination_info ei on er.exam_id=ei.exam_id
where u.level =7 and ei.tag='SQL' and ei.difficulty ='hard'
group by uid
having score >80
),
-- 2.查找考试的用户和统计
tmp_exam as
(
select uid, count(submit_time) exam_cnt
from exam_record
where year(submit_time)='2021'
group by uid
),
tmp_prac as
-- 3.查找练习的用户和统计
(
select uid, count(submit_time) question_cnt
from practice_record
where year(submit_time)='2021'
group by uid
)
select tmp_exam.uid,tmp_exam.exam_cnt,if(tmp_prac.question_cnt,tmp_prac.question_cnt,0) question_cnt
-- 4.考试左外连练习
from tmp_exam left join tmp_prac on tmp_prac.uid=tmp_exam.uid
-- 5.过滤掉不符合的用户uid
where tmp_exam.uid in (select uid from tmp_u)
order by exam_cnt asc ,question_cnt desc
select exam.uid,exam.exam_cnt,if(question_cnt, question_cnt,0) question_cnt
from
(
-- 统计考试的所有用户
select uid,
count(score) as exam_cnt
from exam_record
where year(submit_time) = 2021
group by uid) exam
left join (
-- 练习的所有用户
select uid,
count(score) as question_cnt
from practice_record
where year(submit_time) = 2021
group by uid) prac on exam.uid=prac.uid
where exam.uid in(
select u.uid
from user_info u
join exam_record er on er.uid=u.uid
join examination_info ei on ei.exam_id=er.exam_id
where difficulty='hard'
and level=7
and year(er.submit_time)='2021'
and tag='SQL'
group by uid having avg(score) > 80
)
order by exam_cnt asc,question_cnt desc
select er.uid,
-- count(distinct exam_id,er.submit_time) as exam_cnt,
-- count(distinct exam_id) as exam_cnt,
exam_id, er.submit_time,question_id,pr.submit_time
-- count(distinct question_id, pr.submit_time) as question_cnt
from exam_record er left join practice_record pr
on er.uid = pr.uid and year(pr.submit_time) = 2021
where er.uid in
(select er.uid
from user_info ui right join exam_record er
on ui.uid = er.uid
left join examination_info ei
on er.exam_id = ei.exam_id
where tag = "SQL" and difficulty = "hard" and level = 7
group by er.uid
having avg(score) > 80)
and year(start_time) = 2021
and er.submit_time is not null
group by er.uid
order by exam_cnt, question_cnt desc
-- left join 行数增加,需要去重
uid |exam_id|submit_time |question_id|submit_time |
----+-------+---------------------+-----------+---------------------+
1001| 9001|2021-09-01 09:31:00.0| 8002|2021-08-02 19:38:01.0|
1001| 9001|2021-09-01 09:31:00.0| 8001|2021-08-02 11:41:01.0|
1003| 9001|2021-09-01 19:40:01.0| | |
1003| 9002|2021-09-01 12:31:51.0| | |
SQL26 每个6/7级用户活跃情况
drop table if exists examination_info,user_info,exam_record,practice_record;
CREATE TABLE examination_info (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
exam_id int UNIQUE NOT NULL COMMENT '试卷ID',
tag varchar(32) COMMENT '类别标签',
difficulty varchar(8) COMMENT '难度',
duration int NOT NULL COMMENT '时长',
release_time datetime COMMENT '发布时间'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE TABLE user_info (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int UNIQUE NOT NULL COMMENT '用户ID',
`nick_name` varchar(64) COMMENT '昵称',
achievement int COMMENT '成就值',
level int COMMENT '用户等级',
job varchar(32) COMMENT '职业方向',
register_time datetime COMMENT '注册时间'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE TABLE practice_record (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int NOT NULL COMMENT '用户ID',
question_id int NOT NULL COMMENT '题目ID',
submit_time datetime COMMENT '提交时间',
score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE TABLE exam_record (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int NOT NULL COMMENT '用户ID',
exam_id int NOT NULL COMMENT '试卷ID',
start_time datetime NOT NULL COMMENT '开始时间',
submit_time datetime COMMENT '提交时间',
score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
INSERT INTO user_info(uid,`nick_name`,achievement,level,job,register_time) VALUES
(1001, '牛客1号', 3100, 7, '算法', '2020-01-01 10:00:00'),
(1002, '牛客2号', 2300, 7, '算法', '2020-01-01 10:00:00'),
(1003, '牛客3号', 2500, 7, '算法', '2020-01-01 10:00:00'),
(1004, '牛客4号', 1200, 5, '算法', '2020-01-01 10:00:00'),
(1005, '牛客5号', 1600, 6, 'C++', '2020-01-01 10:00:00'),
(1006, '牛客6号', 2600, 7, 'C++', '2020-01-01 10:00:00');
INSERT INTO examination_info(exam_id,tag,difficulty,duration,release_time) VALUES
(9001, 'SQL', 'hard', 60, '2021-09-01 06:00:00'),
(9002, 'C++', 'easy', 60, '2021-09-01 06:00:00'),
(9003, '算法', 'medium', 80, '2021-09-01 10:00:00');
INSERT INTO practice_record(uid,question_id,submit_time,score) VALUES
(1001, 8001, '2021-08-02 11:41:01', 60),
(1004, 8001, '2021-08-02 19:38:01', 70),
(1004, 8002, '2021-08-02 19:48:01', 90),
(1001, 8002, '2021-08-02 19:38:01', 70),
(1004, 8002, '2021-08-02 19:48:01', 90),
(1006, 8002, '2021-08-04 19:58:01', 94),
(1006, 8003, '2021-08-03 19:38:01', 70),
(1006, 8003, '2021-08-02 19:48:01', 90),
(1006, 8003, '2020-08-01 19:38:01', 80);
INSERT INTO exam_record(uid,exam_id,start_time,submit_time,score) VALUES
(1001, 9001, '2021-09-01 09:01:01', '2021-09-01 09:31:00', 78),
(1001, 9001, '2021-09-01 09:01:01', '2021-09-01 09:31:00', 81),
(1005, 9001, '2021-09-01 19:01:01', '2021-09-01 19:30:01', 85),
(1005, 9002, '2021-09-01 12:01:01', '2021-09-01 12:31:02', 85),
(1006, 9003, '2021-09-07 10:01:01', '2021-09-07 10:21:59', 84),
(1006, 9001, '2021-09-07 10:01:01', '2021-09-07 10:21:01', 81),
(1002, 9001, '2020-09-01 13:01:01', '2020-09-01 13:41:01', 81),
(1005, 9001, '2021-09-01 14:01:01', null, null);
select uid,
count(distinct date_format(submit_time,'%Y%m')) act_month_total,
count(distinct if(date_format(submit_time, '%Y')='2021',date_format(submit_time, '%Y%m%d'),null)) act_days_2021,
count(distinct if(date_format(submit_time, '%Y')='2021' and act='exam',date_format(submit_time, '%Y%m%d'),null)) act_days_2021_exam,
count(distinct if(date_format(submit_time, '%Y')='2021' and act='prac',date_format(submit_time, '%Y%m%d'),null)) act_days_2021_question
from (
select u.uid,submit_time, 'exam' act
from user_info u
left join exam_record er on er.uid=u.uid
where u.level in (6,7)
union all
select u.uid,submit_time, 'prac' act
from user_info u
left join practice_record er on er.uid=u.uid
where u.level in (6,7)
) tmp
group by uid
order by act_month_total desc ,act_days_2021 desc
select
u.uid,
count(distinct all_month) act_month_total,
count(distinct days_2021) act_days_2021,
count(distinct(
case
when year_2021='2021' and tag='exam' then days_2021
else null
end)) act_days_2021_exam,
count(distinct(
case
when year_2021='2021' and tag='prac' then days_2021
else null
end)) act_days_2021_question
from (
select uid
from user_info
where LEVEL in(6,7)
) u
left join
(
select uid, exam_id,
date_format(submit_time,'%Y%m') all_month,
case
when date_format(submit_time,'%Y')='2021' then date_format(submit_time,'%Y%m%d')
else null
end days_2021,
case
when date_format(submit_time,'%Y')='2021' then date_format(submit_time,'%Y')
else null
end year_2021,
'exam' tag
from exam_record er
union all
select uid, question_id,
date_format(submit_time,'%Y%m') all_month,
case
when date_format(submit_time,'%Y')='2021' then date_format(submit_time,'%Y%m%d')
else null
end days_2021,
case
when date_format(submit_time,'%Y')='2021' then date_format(submit_time,'%Y')
else null
end year_2021,
'prac' tag
from practice_record pr
) epall on u.uid=epall.uid
group by uid
order by act_month_total desc ,act_days_2021 desc
drop table if exists examination_info,exam_record;
CREATE TABLE examination_info (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
exam_id int UNIQUE NOT NULL COMMENT '试卷ID',
tag varchar(32) COMMENT '类别标签',
difficulty varchar(8) COMMENT '难度',
duration int NOT NULL COMMENT '时长',
release_time datetime COMMENT '发布时间'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE TABLE exam_record (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int NOT NULL COMMENT '用户ID',
exam_id int NOT NULL COMMENT '试卷ID',
start_time datetime NOT NULL COMMENT '开始时间',
submit_time datetime COMMENT '提交时间',
score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
INSERT INTO examination_info(exam_id,tag,difficulty,duration,release_time) VALUES
(9001, 'SQL', 'hard', 60, '2021-09-01 06:00:00'),
(9002, 'SQL', 'hard', 60, '2021-09-01 06:00:00'),
(9003, '算法', 'medium', 80, '2021-09-01 10:00:00');
INSERT INTO exam_record(uid,exam_id,start_time,submit_time,score) VALUES
(1001, 9001, '2021-09-01 09:01:01', '2021-09-01 09:31:00', 78),
(1001, 9001, '2021-09-01 09:01:01', '2021-09-01 09:31:00', 81),
(1002, 9002, '2021-09-01 12:01:01', '2021-09-01 12:31:01', 81),
(1003, 9001, '2021-09-01 19:01:01', '2021-09-01 19:40:01', 86),
(1003, 9002, '2021-09-01 12:01:01', '2021-09-01 12:31:51', 89),
(1004, 9001, '2021-09-01 19:01:01', '2021-09-01 19:30:01', 85),
(1005, 9003, '2021-09-01 12:01:01', '2021-09-01 12:31:02', 85),
(1006, 9003, '2021-09-07 10:01:01', '2021-09-07 10:21:01', 84),
(1003, 9003, '2021-09-08 12:01:01', '2021-09-08 12:11:01', 40),
(1003, 9002, '2021-09-01 14:01:01', null, null);
select * from (
select tid,uid,
rank() over (partition by tid order by m_score desc,min_score desc,uid desc )rk
from
(
select
tag tid,er.uid,max(score) m_score,min(score) min_score
from exam_record er
join examination_info ei on er.exam_id=ei.exam_id
group by tid, uid
) tmp
) t
where rk <=3
-- 最内层先出结果,取出所有最大分和最小分
-- 外层开窗分区排序,最大分降序,最大分相同最小分降序,还相同按照uid降序
-- 即一个人有多次记录,取最好的一次记录
tid|uid |max(score)|min(score)|
---+----+----------+----------+
SQL|1001| 81| 78|
SQL|1002| 81| 81|
SQL|1003| 89| 86|
SQL|1004| 85| 85|
算法 |1005| 85| 85|
算法 |1006| 84| 84|
算法 |1003| 40| 40|
-- 可以减少一层子查询
select tag, uid, ranking
from(
select tag, e_r.uid,
row_number() over (partition by tag order by max(score) desc, min(score) desc, e_r.uid desc) as ranking
from exam_record e_r join examination_info e_i
on e_r.exam_id = e_i.exam_id
group by tag, e_r.uid
)ranktable
where ranking <= 3
SELECT b.tag,a.uid,max(a.score),min(a.score),/*这里写max(a.score)和min(a.score)是为了帮助理解窗口函数里的ORDER BY 后面的内容*/
ROW_NUMBER()OVER(PARTITION BY tag ORDER BY max(a.score)DESC,min(a.score)DESC,a.uid DESC) ranking
FROM exam_record a
LEFT JOIN examination_info b ON a.exam_id=b.exam_id
GROUP BY b.tag,a.uid;
![](https://secure2.wostatic.cn/static/9hszkx8qMxxjfLWT7PzpLL/image.png)
drop table if exists examination_info,exam_record;
CREATE TABLE examination_info (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
exam_id int UNIQUE NOT NULL COMMENT '试卷ID',
tag varchar(32) COMMENT '类别标签',
difficulty varchar(8) COMMENT '难度',
duration int NOT NULL COMMENT '时长',
release_time datetime COMMENT '发布时间'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE TABLE exam_record (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int NOT NULL COMMENT '用户ID',
exam_id int NOT NULL COMMENT '试卷ID',
start_time datetime NOT NULL COMMENT '开始时间',
submit_time datetime COMMENT '提交时间',
score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
INSERT INTO examination_info(exam_id,tag,difficulty,duration,release_time) VALUES
(9001, 'SQL', 'hard', 60, '2021-09-01 06:00:00'),
(9002, 'C++', 'hard', 60, '2021-09-01 06:00:00'),
(9003, '算法', 'medium', 80, '2021-09-01 10:00:00');
INSERT INTO exam_record(uid,exam_id,start_time,submit_time,score) VALUES
(1001, 9001, '2021-09-01 09:01:01', '2021-09-01 09:51:01', 78),
(1001, 9002, '2021-09-01 09:01:01', '2021-09-01 09:31:00', 81),
(1002, 9002, '2021-09-01 12:01:01', '2021-09-01 12:31:01', 81),
(1003, 9001, '2021-09-01 19:01:01', '2021-09-01 19:59:01', 86),
(1003, 9002, '2021-09-01 12:01:01', '2021-09-01 12:31:51', 89),
(1004, 9002, '2021-09-01 19:01:01', '2021-09-01 19:30:01', 85),
(1005, 9001, '2021-09-01 12:01:01', '2021-09-01 12:31:02', 85),
(1006, 9001, '2021-09-07 10:01:01', '2021-09-07 10:12:01', 84),
(1003, 9001, '2021-09-08 12:01:01', '2021-09-08 12:11:01', 40),
(1003, 9002, '2021-09-01 14:01:01', null, null),
(1005, 9001, '2021-09-01 14:01:01', null, null),
(1003, 9003, '2021-09-08 15:01:01', null, null);
解法
第一种方法
1.通过窗口函数构造一张虚表,存放正序和倒叙用时的数据
select exam_id,timestampdiff(second,start_time,submit_time) used_time,
ROW_NUMBER() over(partition by exam_id order by timestampdiff(second,start_time,submit_time) asc) rk_short_use_time , -- 升序,第二快
ROW_NUMBER() over(partition by exam_id order by timestampdiff(second,start_time,submit_time) desc ) rk_long_use_time -- 降序,第二慢
from exam_record er
where submit_time is not null
+---------+-----------+-------------------+------------------+
| exam_id | used_time | rk_short_use_time | rk_long_use_time |
+---------+-----------+-------------------+------------------+
| 9001 | 1800 | 2 | 1 |
| 9001 | 1200 | 1 | 2 |
| 9002 | 3481 | 12 | 1 |
| 9002 | 3420 | 11 | 2 |
| 9002 | 3410 | 10 | 3 |
| 9002 | 1801 | 9 | 4 |
| 9002 | 1800 | 5 | 5 |
| 9002 | 1800 | 6 | 6 |
| 9002 | 1800 | 7 | 7 |
| 9002 | 1800 | 8 | 8 |
| 9002 | 1799 | 4 | 9 |
| 9002 | 1740 | 3 | 10 |
| 9002 | 1200 | 2 | 11 |
| 9002 | 540 | 1 | 12 |
| 9003 | 3480 | 5 | 1 |
| 9003 | 3010 | 4 | 2 |
| 9003 | 1801 | 3 | 3 |
| 9003 | 1201 | 2 | 4 |
| 9003 | 600 | 1 | 5 |
2.两次使用虚表,将相同ID的数据放到一行
with tmp as
(
select exam_id,timestampdiff(second,start_time,submit_time) used_time,
ROW_NUMBER() over(partition by exam_id order by timestampdiff(second,start_time,submit_time) asc) rk_short_use_time , -- 升序,第二快
ROW_NUMBER() over(partition by exam_id order by timestampdiff(second,start_time,submit_time) desc ) rk_long_use_time -- 降序,第二慢
from exam_record er
where submit_time is not null
)
select lon.exam_id,long_time,short_time from
(select exam_id,used_time long_time from tmp where rk_long_use_time=2) lon
left join (select exam_id,used_time short_time from tmp where rk_short_use_time=2) shor on lon.exam_id=shor.exam_id
+---------+-----------+------------+
| exam_id | long_time | short_time |
+---------+-----------+------------+
| 9001 | 1200 | 1800 |
| 9002 | 3420 | 1200 |
| 9003 | 3010 | 1201 |
+---------+-----------+------------+
3.和试卷表关联,长时间减去短时间的差值大于duration的一半
with tmp as
(
select exam_id,timestampdiff(second,start_time,submit_time) used_time,
ROW_NUMBER() over(partition by exam_id order by timestampdiff(second,start_time,submit_time) asc) rk_short_use_time , -- 升序,第二快
ROW_NUMBER() over(partition by exam_id order by timestampdiff(second,start_time,submit_time) desc ) rk_long_use_time -- 降序,第二慢
from exam_record er
where submit_time is not null
)
select lon.exam_id,long_time,short_time from
(select exam_id,used_time long_time from tmp where rk_long_use_time=2) lon
left join (select exam_id,used_time short_time from tmp where rk_short_use_time=2) shor on lon.exam_id=shor.exam_id
join examination_info ei on lon.exam_id=ei.exam_id
where (long_time - short_time) > duration*60/2
order by exam_id desc
+---------+-----------+------------+
| exam_id | long_time | short_time |
+---------+-----------+------------+
| 9003 | 3010 | 1201 |
| 9002 | 3420 | 1200 |
+---------+-----------+------------+
- 第二种方法
通过NTH_VALUE取倒叙、升序第二个差值(用时)????
![](https://secure2.wostatic.cn/static/3mEDsHcPVvbvdRhAwxrhcQ/image.png)
- 第三种方法
select ei.exam_id,duration,release_time,man_2,kuai_2 from
(
select exam_id,max(if(rank2=2,time_diff, null)) man_2,max(if(rank1=2,time_diff, null)) kuai_2
from (
select
exam_id,
TIMESTAMPDIFF(second,start_time, submit_time) as time_diff
,row_number()over(partition by exam_id order by TIMESTAMPDIFF(second,start_time,submit_time)) as rank1 -- 升序最快
,row_number()over(partition by exam_id order by TIMESTAMPDIFF(second,start_time,submit_time) desc) as rank2 -- 降序最慢
from exam_record where submit_time is not null
) t
group by exam_id
) tmp
join examination_info ei on ei.exam_id=tmp.exam_id
where man_2-kuai_2 > duration*60/2
order by exam_id desc
exam_id|duration|release_time |man_2|kuai_2|
-------+--------+---------------------+-----+------+
9003| 60|2021-09-01 10:00:00.0| 3010| 1201|
9002| 60|2021-09-01 08:00:00.0| 3420| 1200|
+---------+-----------+-------+-------+
| exam_id | time_diff | rank1 | rank2 |
+---------+-----------+-------+-------+
| 9001 | 1800 | 2 | 1 |
| 9001 | 1200 | 1 | 2 |
**| 9002 | 3481 | 12 | 1 |
| 9002 | 3420 | 11 | 2 |
| 9002 | 3410 | 10 | 3 |
| 9002 | 1801 | 9 | 4 |
| 9002 | 1800 | 5 | 5 |
| 9002 | 1800 | 6 | 6 |
| 9002 | 1800 | 7 | 7 |
| 9002 | 1800 | 8 | 8 |
| 9002 | 1799 | 4 | 9 |
| 9002 | 1740 | 3 | 10 |
| 9002 | 1200 | 2 | 11 |
| 9002 | 540 | 1 | 12 |**
| 9003 | 3480 | 5 | 1 |
| 9003 | 3010 | 4 | 2 |
| 9003 | 1801 | 3 | 3 |
| 9003 | 1201 | 2 | 4 |
| 9003 | 600 | 1 | 5 |
+---------+-----------+-------+-------+
drop table if exists exam_record;
CREATE TABLE exam_record (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int NOT NULL COMMENT '用户ID',
exam_id int NOT NULL COMMENT '试卷ID',
start_time datetime NOT NULL COMMENT '开始时间',
submit_time datetime COMMENT '提交时间',
score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
INSERT INTO exam_record(uid,exam_id,start_time,submit_time,score) VALUES
(1006, 9003, '2021-09-07 10:01:01', '2021-09-07 10:21:02', 84),
(1006, 9001, '2021-09-01 12:11:01', '2021-09-01 12:31:01', 89),
(1006, 9002, '2021-09-06 10:01:01', '2021-09-06 10:21:01', 81),
(1005, 9002, '2021-09-05 10:01:01', '2021-09-05 10:21:01', 81),
(1005, 9001, '2021-09-05 10:31:01', '2021-09-05 10:51:01', 81);
+------------------------------+
| datediff('2022-03-04',now()) |
+------------------------------+
| -15 |
+------------------------------+
1 row in set (0.00 sec)
root@hadoop102 18:39: [test]> select timestampdiff(second,'2022-03-04',now());
+------------------------------------------+
| timestampdiff(second,'2022-03-04',now()) |
+------------------------------------------+
| 1363194 |
+------------------------------------------+
1 row in set (0.00 sec)
root@hadoop102 18:39: [test]> select timestampdiff(second,now(),'2022-03-04');
+------------------------------------------+
| timestampdiff(second,now(),'2022-03-04') |
+------------------------------------------+
| -1363211 |
+------------------------------------------+
with tmp as (
select
uid,exam_id,start_time start_time ,
lead(start_time,1) over (partition by uid order by start_time asc ) next_time
from exam_record
where year(start_time)='2021'
)
select uid, days_windows, round(exam_cnt/diff_days*days_windows,2) avg_exam_cnt
from (
select uid,
count(uid) exam_cnt, -- 做过的试卷次数
datediff(max(next_time),min(start_time)) +1 diff_days, -- 最大间隔天数 超过1,则表示有两天答题
max(datediff(next_time,start_time)) +1 days_windows -- 最大时间窗 要用start_time,submit_time数据不通过
from tmp
group by uid
)t
where diff_days >1
order by days_windows desc ,avg_exam_cnt desc
![](https://secure2.wostatic.cn/static/qK4NrdZAZomjY6r2ZrYRmY/image.png)
![](https://secure2.wostatic.cn/static/qPJYF3QNbqpLPhozLUArpc/image.png)
select uid,days_window,round(cnt/diff_days * days_window,2) avg_exam_cnt from (
select uid,count(start_time) cnt,
min(start_time),max(next_start_time),
datediff(max(next_start_time),min(start_time)) +1 diff_days,
max(datediff(next_start_time, start_time))+1 days_window
from (
select uid,exam_id,start_time,
lead(start_time,1) over (partition by uid order by start_time) as next_start_time
from exam_record
where year(start_time)='2021'
) t
group by uid
) tmp
where diff_days >=2
order by days_window desc ,avg_exam_cnt desc
with
a as ( -- 明确用户每次做题相邻时间窗、用户该年参与做题总数
select uid,
date(start_time) as st, -- 该用户本次答卷日期
DATEDIFF(date(lead(start_time) over(partition by uid order by start_time)),date(start_time))+1 as st_window, -- 该用户相邻答卷天数差时间窗(从题意看,时间差要把起始天算进去,所以+1)
count(uid) over(partition by uid order by uid) as year_total -- 该用户当年答卷总数
from exam_record
where year(start_time)=2021
),
b as ( -- 明确用户最大做题相邻时间窗、用户全年起止做题时间窗
select uid,
max(st_window) as max_window, -- 该用户最大相邻时间窗
year_total, -- 该用户今年总答卷数
DATEDIFF(max(st),min(st))+1 as year_window -- 该用户今年起止答卷天数差
from a
group by uid
)
select
uid,
max_window as days_window,
round(year_total/year_window*max_window,2) as avg_exam_cnt -- 题意解释里要求的计算方法
from b
where max_window>1 -- 题意要求参与至少2天(最大相邻窗口1天的,就只参与了1天,不符合要求)
order by days_window desc,avg_exam_cnt desc
INSERT INTO exam_record(uid,exam_id,start_time,submit_time,score) VALUES
(1006, 9003, '2021-09-06 10:01:01', '2021-09-06 10:21:02', 84),
(1006, 9001, '2021-08-02 12:11:01', '2021-08-02 12:31:01', 89),
(1006, 9002, '2021-06-06 10:01:01', '2021-06-06 10:21:01', 81),
(1006, 9002, '2021-06-06 10:01:01', '2021-06-06 10:21:01', 81),
(1006, 9001, '2021-05-01 12:01:01', null, null),
(1001, 9001, '2021-09-05 10:31:01', '2021-09-05 10:51:01', 81),
(1001, 9003, '2021-08-01 09:01:01', '2021-08-01 09:51:11', 78),
(1001, 9002, '2021-07-01 09:01:01', '2021-07-01 09:31:00', 81),
(1001, 9002, '2021-07-01 12:01:01', '2021-07-01 12:31:01', 81),
(1001, 9002, '2021-07-01 12:01:01', null, null),
(1003, 9003, '2021-09-01 19:01:01', '2021-09-01 19:59:01', 86),
(1003, 9002, '2021-09-03 12:01:01', '2021-09-03 12:57:51', 89),
(1003, 9003, '2021-08-07 12:01:01', '2021-08-07 12:11:01', 40),
(1003, 9003, '2021-05-08 15:01:01', null, null),
(1003, 9002, '2021-06-01 13:01:01', '2021-06-01 13:58:01', 81);
select uid,count(if(score,1,null)) exam_complete_cnt from (
select uid,exam_id,score,
dense_rank() over (partition by uid order by date_format(start_time, '%Y%m') desc) rk -- 注意排序要到月份
from exam_record
) t
where rk <=3
group by uid having exam_complete_cnt =count(uid)
order by exam_complete_cnt desc,uid desc
drop table if exists examination_info,exam_record;
CREATE TABLE examination_info (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
exam_id int UNIQUE NOT NULL COMMENT '试卷ID',
tag varchar(32) COMMENT '类别标签',
difficulty varchar(8) COMMENT '难度',
duration int NOT NULL COMMENT '时长',
release_time datetime COMMENT '发布时间'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE TABLE exam_record (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int NOT NULL COMMENT '用户ID',
exam_id int NOT NULL COMMENT '试卷ID',
start_time datetime NOT NULL COMMENT '开始时间',
submit_time datetime COMMENT '提交时间',
score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
INSERT INTO examination_info(exam_id,tag,difficulty,duration,release_time) VALUES
(9001, 'SQL', 'hard', 60, '2020-01-01 10:00:00'),
(9002, 'C++', 'hard', 80, '2020-01-01 10:00:00'),
(9003, '算法', 'hard', 80, '2020-01-01 10:00:00'),
(9004, 'PYTHON', 'medium', 70, '2020-01-01 10:00:00');
INSERT INTO exam_record(uid,exam_id,start_time,submit_time,score) VALUES
(1001, 9001, '2020-08-02 10:01:01', '2020-08-02 10:31:01', 89),
(1002, 9001, '2020-04-01 18:01:01', '2020-04-01 18:59:02', 90),
(1001, 9001, '2020-04-01 09:01:01', '2020-04-01 09:21:59', 80),
(1002, 9003, '2021-01-20 10:01:01', '2021-01-20 10:10:01', 81),
(1002, 9001, '2021-03-02 19:01:01', '2021-03-02 19:32:00', 20),
(1001, 9003, '2021-04-02 19:01:01', '2021-04-02 19:40:01', 89),
(1004, 9004, '2020-05-02 12:01:01', '2020-05-02 12:20:01', 99),
(1003, 9001, '2021-05-02 12:01:01', '2021-05-02 12:31:01', 98),
(1001, 9002, '2020-02-02 12:01:01', '2020-02-02 12:20:01', 99),
(1002, 9002, '2020-02-02 12:01:01', '2020-02-02 12:43:01', 81),
(1001, 9002, '2020-01-02 19:01:01', '2020-01-02 19:59:01', 69),
(1001, 9004, '2021-09-02 12:11:01', null, null),
(1003, 9001, '2020-01-02 10:01:01', '2020-01-02 10:31:01', 89),
(1002, 9004, '2020-01-01 12:11:01', '2020-01-01 12:31:01', 83),
(1002, 9003, '2021-01-01 18:01:01', '2021-01-01 18:59:02', 90),
(1002, 9002, '2020-02-02 12:01:01', null, null),
(1002, 9002, '2020-03-02 12:11:01', null, null),
(1001, 9002, '2021-05-05 18:01:01', null, null);
select tag,exam_cnt_20,exam_cnt_21, growth_rate,
exam_cnt_rank_20,
exam_cnt_rank_21,
cast(exam_cnt_rank_21 as signed) - cast(exam_cnt_rank_20 as signed) rank_delta -- 转为有符号整形
from
(
select tag,exam_cnt_20,exam_cnt_21,
concat(round(ifnull((exam_cnt_21-exam_cnt_20)/exam_cnt_20*100,0),1),'%') growth_rate, -- 拼接百分比
rank() over (order by exam_cnt_20 desc ) exam_cnt_rank_20, -- 为什么是倒序? 去年降序,今年降序,升序的话两年的排名相同了
rank() over (order by exam_cnt_21 desc) exam_cnt_rank_21
from
(select tag,
sum(if(date_format(submit_time,'%Y%m') between '202001' and '202006' ,1,0)) exam_cnt_20, -- 行转列1
sum(if(date_format(submit_time,'%Y%m') between '202101' and '202106' ,1,0)) exam_cnt_21 -- 行转列2
from exam_record er
join examination_info ei on er.exam_id=ei.exam_id
group by tag) t
)t
where exam_cnt_20 !=0 and exam_cnt_21 !=0
order by growth_rate desc,exam_cnt_rank_21 desc
![](https://secure2.wostatic.cn/static/pjmf3ciCuZtxs4wdEGFm4H/image.png)
![](https://secure2.wostatic.cn/static/hJTtxB6sDWEvUy6SW58Sma/image.png)
![](https://secure2.wostatic.cn/static/jFGAiK1gMN1iRAx1Kp8HHT/image.png)
![](https://secure2.wostatic.cn/static/sU3mRbW7drGgMEAPwbwfXS/image.png)
drop table if exists examination_info,exam_record;
CREATE TABLE examination_info (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
exam_id int UNIQUE NOT NULL COMMENT '试卷ID',
tag varchar(32) COMMENT '类别标签',
difficulty varchar(8) COMMENT '难度',
duration int NOT NULL COMMENT '时长',
release_time datetime COMMENT '发布时间'
)CHARACTER SET utf8 COLLATE utf8_bin;
CREATE TABLE exam_record (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int NOT NULL COMMENT '用户ID',
exam_id int NOT NULL COMMENT '试卷ID',
start_time datetime NOT NULL COMMENT '开始时间',
submit_time datetime COMMENT '提交时间',
score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
INSERT INTO examination_info(exam_id,tag,difficulty,duration,release_time) VALUES
(9001, 'SQL', 'hard', 60, '2020-01-01 10:00:00'),
(9002, 'C++', 'hard', 80, '2020-01-01 10:00:00'),
(9003, '算法', 'hard', 80, '2020-01-01 10:00:00'),
(9004, 'PYTHON', 'medium', 70, '2020-01-01 10:00:00'),
(9005, 'WEB', 'hard', 80, '2020-01-01 10:00:00'),
(9006, 'PYTHON', 'hard', 80, '2020-01-01 10:00:00'),
(9007, 'web', 'hard', 80, '2020-01-01 10:00:00'),
(9008, 'Web', 'medium', 70, '2020-01-01 10:00:00'),
(9009, 'WEB', 'medium', 70, '2020-01-01 10:00:00'),
(9010, 'SQL', 'medium', 70, '2020-01-01 10:00:00');
INSERT INTO exam_record(uid,exam_id,start_time,submit_time,score) VALUES
(1001, 9001, '2020-01-01 09:01:01', '2020-01-01 09:21:59', 90),
(1003, 9002, '2020-01-01 19:01:01', '2020-01-01 19:30:01', 75),
(1004, 9002, '2020-01-01 12:01:01', '2020-01-01 12:11:01', 60),
(1003, 9002, '2020-01-01 12:01:01', '2020-01-01 12:41:01', 90),
(1002, 9002, '2020-01-02 19:01:01', '2020-01-02 19:32:00', 90),
(1003, 9001, '2020-01-02 12:01:01', '2020-01-02 12:31:01', 68),
(1001, 9002, '2020-01-02 12:01:01', '2020-01-02 12:43:01', 81),
(1001, 9005, '2020-01-02 12:11:01', null, null),
(1001, 9001, '2020-01-02 10:01:01', '2020-01-02 10:31:01', 89),
(1002, 9002, '2020-01-01 12:11:01', '2020-01-01 12:31:01', 83),
(1002, 9004, '2021-09-06 12:01:01', null, null),
(1002, 9002, '2021-05-05 18:01:01', null, null);
select
uid,exam_id,
round(avg(if(max_score!=min_score,(score-min_score)/(max_score-min_score)*100,score))) as new_score
-- 为什么要判断 max_score!=min_score 某个试卷作答记录中只有一个得分,那么无需使用公式
-- 当min(score)=max(score)那就说明只有一个得分
from
(select er.uid,er.exam_id,er.score,
min(score) over (partition by er.exam_id ) min_score,
max(score) over (partition by er.exam_id ) max_score
from exam_record er
join examination_info ei on er.exam_id=ei.exam_id
where ei.difficulty='hard' and score is not null)
t
group by uid,exam_id
order by exam_id,new_score desc
drop table if exists exam_record;
CREATE TABLE exam_record (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int NOT NULL COMMENT '用户ID',
exam_id int NOT NULL COMMENT '试卷ID',
start_time datetime NOT NULL COMMENT '开始时间',
submit_time datetime COMMENT '提交时间',
score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
INSERT INTO exam_record(uid,exam_id,start_time,submit_time,score) VALUES
(1001, 9001, '2020-01-01 09:01:01', '2020-01-01 09:21:59', 90),
(1002, 9001, '2020-01-20 10:01:01', '2020-01-20 10:10:01', 89),
(1002, 9001, '2020-02-01 12:11:01', '2020-02-01 12:31:01', 83),
(1003, 9001, '2020-03-01 19:01:01', '2020-03-01 19:30:01', 75),
(1004, 9001, '2020-03-01 12:01:01', '2020-03-01 12:11:01', 60),
(1003, 9001, '2020-03-01 12:01:01', '2020-03-01 12:41:01', 90),
(1002, 9001, '2020-05-02 19:01:01', '2020-05-02 19:32:00', 90),
(1001, 9002, '2020-01-02 19:01:01', '2020-01-02 19:59:01', 69),
(1004, 9002, '2020-02-02 12:01:01', '2020-02-02 12:20:01', 99),
(1003, 9002, '2020-02-02 12:01:01', '2020-02-02 12:31:01', 68),
(1001, 9002, '2020-02-02 12:01:01', '2020-02-02 12:43:01', 81),
(1001, 9002, '2020-03-02 12:11:01', null, null);
select exam_id,start_month,month_cnt,
sum(month_cnt) over (partition by exam_id order by start_month ) cum_exam_cnt
from
(select distinct exam_id, start_month,
count(start_month) over (partition by exam_id,start_month order by exam_id,start_month) month_cnt
from (
select exam_id, date_format(start_time,'%Y%m') start_month
from exam_record
) t
) t
select exam_id,start_month, month_cnt,
-- 每试卷累计按月份排序
sum(month_cnt) over (partition by exam_id order by start_month) cum_exam_cnt
from
(
select exam_id,date_format(start_time,'%Y%m') start_month,
-- 当月的次数直接分组求count
count(date_format(start_time,'%Y%m')) month_cnt
from exam_record
group by exam_id,start_month
) t
drop table if exists exam_record;
CREATE TABLE exam_record (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int NOT NULL COMMENT '用户ID',
exam_id int NOT NULL COMMENT '试卷ID',
start_time datetime NOT NULL COMMENT '开始时间',
submit_time datetime COMMENT '提交时间',
score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
INSERT INTO exam_record(uid,exam_id,start_time,submit_time,score) VALUES
(1001, 9001, '2020-01-01 09:01:01', '2020-01-01 09:21:59', 90),
(1002, 9001, '2020-01-20 10:01:01', '2020-01-20 10:10:01', 89),
(1002, 9001, '2020-02-01 12:11:01', '2020-02-01 12:31:01', 83),
(1003, 9001, '2020-03-01 19:01:01', '2020-03-01 19:30:01', 75),
(1004, 9001, '2020-03-01 12:01:01', '2020-03-01 12:11:01', 60),
(1003, 9001, '2020-03-01 12:01:01', '2020-03-01 12:41:01', 90),
(1002, 9001, '2020-05-02 19:01:01', '2020-05-02 19:32:00', 90),
(1001, 9002, '2020-01-02 19:01:01', '2020-01-02 19:59:01', 69),
(1004, 9002, '2020-02-02 12:01:01', '2020-02-02 12:20:01', 99),
(1003, 9002, '2020-02-02 12:01:01', '2020-02-02 12:31:01', 68),
(1001, 9002, '2020-02-02 12:01:01', '2020-02-02 12:43:01', 81),
(1001, 9002, '2020-03-02 12:11:01', null, null);
坑1:新增用户的定义——首次登录的用户,也就是把用户最早登录的那天定义为首次登录日期。
坑2:截止当月的单月最大新增用户数:按照月份依次对比每个月的新增用户数的大小取大值用MAX()OVER(order by start_month)
坑3:截止当月的累积用户数:按照月份依次累加新增用户数用SUM()OVER(ORDER BY start_month)
![](https://secure2.wostatic.cn/static/dtrGgQBJ9bZtuqVrMzMf4f/image.png)
![](https://secure2.wostatic.cn/static/kKSwp3AKh9s9vL9tTZa3B9/image.png)
![左外连接](https://secure2.wostatic.cn/static/cte3EaMYzskmgq1KoLahGt/image.png)
![取max当月最大新增用户,累计每月新增的用户](https://secure2.wostatic.cn/static/kkwb2duXbSosgn3ZiuQNKx/image.png)
select start_month,mau,month_add_uv,
max(month_add_uv) over(order by start_month) max_month_add_uv, -- 截止当月的单月最大新增用户数
sum(month_add_uv) over(order by start_month) cum_sum_uv -- 截止当月的累积用户数
from (
select mau_t.start_month,mau_t.mau,if(new_t.month_add_uv,new_t.month_add_uv,0) month_add_uv
from(
select date_format(start_time ,'%Y%m') start_month,count(distinct uid) mau
from exam_record
group by date_format(start_time ,'%Y%m') )mau_t
left join
(
select start_month,count(distinct uid) month_add_uv
from
(select min(date_format(start_time ,'%Y%m')) start_month, uid
from exam_record
group by uid) t
group by start_month) new_t on mau_t.start_month=new_t.start_month
) t
order by start_month
SQL36 统计有未完成状态的试卷的未完成数和未完成率
drop table if exists exam_record;
CREATE TABLE exam_record (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int NOT NULL COMMENT '用户ID',
exam_id int NOT NULL COMMENT '试卷ID',
start_time datetime NOT NULL COMMENT '开始时间',
submit_time datetime COMMENT '提交时间',
score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
INSERT INTO exam_record(uid,exam_id,start_time,submit_time,score) VALUES
(1001, 9001, '2020-01-02 09:01:01', '2020-01-02 09:21:01', 80),
(1001, 9001, '2021-05-02 10:01:01', '2021-05-02 10:30:01', 81),
(1001, 9001, '2021-09-02 12:01:01', null, null);
select exam_id,count(if(submit_time,null,1)) incomplete_cnt ,round(sum(if(submit_time,0,1))/count(*),3) incomplete_rate
from exam_record
where exam_id in(select exam_id from exam_record where submit_time is null)
group by exam_id
select exam_id,count(if(submit_time,null,1)) incomplete_cnt ,round(sum(if(submit_time,0,1))/count(*),3) incomplete_rate
from exam_record
group by exam_id
having incomplete_cnt >0 -- 存在为完成
SQL37 0级用户高难度试卷的平均用时和平均得分
drop table if exists examination_info,user_info,exam_record;
CREATE TABLE examination_info (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
exam_id int UNIQUE NOT NULL COMMENT '试卷ID',
tag varchar(32) COMMENT '类别标签',
difficulty varchar(8) COMMENT '难度',
duration int NOT NULL COMMENT '时长',
release_time datetime COMMENT '发布时间'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE TABLE user_info (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int UNIQUE NOT NULL COMMENT '用户ID',
`nick_name` varchar(64) COMMENT '昵称',
achievement int COMMENT '成就值',
level int COMMENT '用户等级',
job varchar(32) COMMENT '职业方向',
register_time datetime COMMENT '注册时间'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE TABLE exam_record (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int NOT NULL COMMENT '用户ID',
exam_id int NOT NULL COMMENT '试卷ID',
start_time datetime NOT NULL COMMENT '开始时间',
submit_time datetime COMMENT '提交时间',
score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
INSERT INTO user_info(uid,`nick_name`,achievement,level,job,register_time) VALUES
(1001, '牛客1号', 10, 0, '算法', '2020-01-01 10:00:00'),
(1002, '牛客2号', 2100, 6, '算法', '2020-01-01 10:00:00');
INSERT INTO examination_info(exam_id,tag,difficulty,duration,release_time) VALUES
(9001, 'SQL', 'hard', 60, '2020-01-01 10:00:00'),
(9002, 'SQL', 'easy', 60, '2020-01-01 10:00:00'),
(9004, '算法', 'medium', 80, '2020-01-01 10:00:00');
INSERT INTO exam_record(uid,exam_id,start_time,submit_time,score) VALUES
(1001, 9001, '2020-01-02 09:01:01', '2020-01-02 09:21:59', 80),
(1001, 9001, '2021-05-02 10:01:01', null, null),
(1001, 9002, '2021-02-02 19:01:01', '2021-02-02 19:30:01', 87),
(1001, 9001, '2021-06-02 19:01:01', '2021-06-02 19:32:00', 20),
(1001, 9002, '2021-09-05 19:01:01', '2021-09-05 19:40:01', 89),
(1001, 9002, '2021-09-01 12:01:01', null, null),
(1002, 9002, '2021-05-05 18:01:01', '2021-05-05 18:59:02', 90);
SELECT er.uid,
round(avg(if(score,score,0)),0) avg_score,
round(avg(TIMESTAMPDIFF(MINUTE,start_time, if(submit_time,submit_time,date_add(start_time,interval duration minute)))),1) submit_time
from exam_record er
join examination_info ei on er.exam_id=ei.exam_id
join user_info u on u.uid=er.uid
where level=0 and ei.difficulty='hard'
group by uid
SQL38 筛选限定昵称成就值活跃日期的用户
drop table if exists user_info,exam_record,practice_record;
CREATE TABLE user_info (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int UNIQUE NOT NULL COMMENT '用户ID',
`nick_name` varchar(64) COMMENT '昵称',
achievement int COMMENT '成就值',
level int COMMENT '用户等级',
job varchar(32) COMMENT '职业方向',
register_time datetime COMMENT '注册时间'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE TABLE practice_record (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int NOT NULL COMMENT '用户ID',
question_id int NOT NULL COMMENT '题目ID',
submit_time datetime COMMENT '提交时间',
score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE TABLE exam_record (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int NOT NULL COMMENT '用户ID',
exam_id int NOT NULL COMMENT '试卷ID',
start_time datetime NOT NULL COMMENT '开始时间',
submit_time datetime COMMENT '提交时间',
score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
INSERT INTO user_info(uid,`nick_name`,achievement,level,job,register_time) VALUES
(1001, '牛客1号', 1000, 2, '算法', '2020-01-01 10:00:00'),
(1002, '牛客2号', 1200, 3, '算法', '2020-01-01 10:00:00'),
(1003, '进击的3号', 2200, 5, '算法', '2020-01-01 10:00:00'),
(1004, '牛客4号', 2500, 6, '算法', '2020-01-01 10:00:00'),
(1005, '牛客5号', 3000, 7, 'C++', '2020-01-01 10:00:00');
INSERT INTO practice_record(uid,question_id,submit_time,score) VALUES
(1001, 8001, '2021-08-02 11:41:01', 60),
(1002, 8001, '2021-09-02 19:30:01', 50),
(1002, 8001, '2021-09-02 19:20:01', 70),
(1002, 8002, '2021-09-02 19:38:01', 70),
(1003, 8002, '2021-09-01 19:38:01', 80);
INSERT INTO exam_record(uid,exam_id,start_time,submit_time,score) VALUES
(1001, 9001, '2020-01-02 09:01:01', '2020-01-02 09:21:59', 80),
(1001, 9001, '2021-05-02 10:01:01', null, null),
(1001, 9002, '2021-02-02 19:01:01', '2021-02-02 19:30:01', 87),
(1001, 9001, '2021-06-02 19:01:01', '2021-06-02 19:32:00', 20),
(1001, 9002, '2021-09-05 19:01:01', '2021-09-05 19:40:01', 89),
(1001, 9002, '2021-09-01 12:01:01', null, null),
(1002, 9002, '2021-05-05 18:01:01', '2021-05-05 18:59:02', 90),
(1003, 9003, '2021-02-06 12:01:01', null, null),
(1003, 9001, '2021-09-07 10:01:01', '2021-09-07 10:31:01', 89),
(1004, 9002, '2021-08-06 12:01:01', null, null),
(1002, 9001, '2020-01-01 12:01:01', '2020-01-01 12:31:01', 81),
(1002, 9002, '2020-02-01 12:01:01', '2020-02-01 12:31:01', 82),
(1002, 9002, '2020-02-02 12:11:01', '2020-02-02 12:31:01', 83),
(1005, 9001, '2021-02-01 11:01:01', '2021-02-01 11:31:01', 84),
(1006, 9001, '2021-02-01 11:01:01', '2021-02-01 11:31:01', 84),
(1002, 9001, '2021-09-06 12:01:01', '2021-09-06 12:21:01', 80),
(1002, 9001, '2021-09-06 12:01:01', null, null),
(1002, 9001, '2021-09-07 12:01:01', null, null);
select u.uid,nick_name,achievement
from user_info u
where u.achievement between 1200 and 2500
and u.nick_name like '牛客%号'
and uid in (
select uid from (
select uid,max(date_format(submit_time,'%Y%m')) last_month from
practice_record pr
group by uid
union
select uid,max(date_format(start_time,'%Y%m')) last_month from
exam_record pr
group by uid
) t where last_month='202109'
)
select u.uid,nick_name,achievement
from user_info u
where u.achievement between 1200 and 2500
and u.nick_name like '牛客%号'
and uid in (
select uid from
practice_record pr
where date_format(submit_time,'%Y%m')='202109'
union
select uid from
exam_record pr
where date_format(start_time,'%Y%m')='202109'
)
select uid,nick_name,achievement
from user_info
where nick_name like '牛客%号' and achievement >= 1200 and achievement <= 2500
and uid in (
select uid
from (
select uid,date_format(start_time,'%Y%m') as month
from exam_record
union
select uid,date_format(submit_time,'%Y%m') as month
from practice_record
) t
group by uid
having max(month) = '202109'
)
SQL39 筛选昵称规则和试卷规则的作答记录
drop table if exists examination_info,user_info,exam_record;
CREATE TABLE examination_info (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
exam_id int UNIQUE NOT NULL COMMENT '试卷ID',
tag varchar(32) COMMENT '类别标签',
difficulty varchar(8) COMMENT '难度',
duration int NOT NULL COMMENT '时长',
release_time datetime COMMENT '发布时间'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE TABLE user_info (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int UNIQUE NOT NULL COMMENT '用户ID',
`nick_name` varchar(64) COMMENT '昵称',
achievement int COMMENT '成就值',
level int COMMENT '用户等级',
job varchar(32) COMMENT '职业方向',
register_time datetime COMMENT '注册时间'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE TABLE exam_record (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int NOT NULL COMMENT '用户ID',
exam_id int NOT NULL COMMENT '试卷ID',
start_time datetime NOT NULL COMMENT '开始时间',
submit_time datetime COMMENT '提交时间',
score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
INSERT INTO user_info(uid,`nick_name`,achievement,level,job,register_time) VALUES
(1001, '牛客1', 1900, 2, '算法', '2020-01-01 10:00:00'),
(1002, '牛客2号', 1200, 3, '算法', '2020-01-01 10:00:00'),
(1003, '牛客3号♂', 2200, 5, '算法', '2020-01-01 10:00:00'),
(1004, '牛客4号', 2500, 6, '算法', '2020-01-01 10:00:00'),
(1005, '牛客555号', 2000, 7, 'C++', '2020-01-01 10:00:00'),
(1006, '666666', 3000, 6, 'C++', '2020-01-01 10:00:00');
INSERT INTO examination_info(exam_id,tag,difficulty,duration,release_time) VALUES
(9001, 'C++', 'hard', 60, '2020-01-01 10:00:00'),
(9002, 'c#', 'hard', 80, '2020-01-01 10:00:00'),
(9003, 'SQL', 'medium', 70, '2020-01-01 10:00:00');
INSERT INTO exam_record(uid,exam_id,start_time,submit_time,score) VALUES
(1001, 9001, '2020-01-02 09:01:01', '2020-01-02 09:21:59', 80),
(1001, 9001, '2021-05-02 10:01:01', null, null),
(1001, 9002, '2021-02-02 19:01:01', '2021-02-02 19:30:01', 87),
(1001, 9001, '2021-06-02 19:01:01', '2021-06-02 19:32:00', 20),
(1001, 9002, '2021-09-05 19:01:01', '2021-09-05 19:40:01', 89),
(1001, 9002, '2021-09-01 12:01:01', null, null),
(1002, 9002, '2021-05-05 18:01:01', '2021-05-05 18:59:02', 90),
(1003, 9003, '2021-02-06 12:01:01', null, null),
(1003, 9001, '2021-09-07 10:01:01', '2021-09-07 10:31:01', 89),
(1004, 9002, '2021-08-06 12:01:01', null, null),
(1002, 9001, '2020-01-01 12:01:01', '2020-01-01 12:31:01', 81),
(1002, 9002, '2020-02-01 12:01:01', '2020-02-01 12:31:01', 82),
(1002, 9002, '2020-02-02 12:11:01', '2020-02-02 12:31:01', 83),
(1005, 9001, '2021-02-01 11:01:01', '2021-02-01 11:31:01', 84),
(1006, 9001, '2021-09-01 11:01:01', '2021-09-01 11:31:01', 84),
(1002, 9001, '2021-09-06 12:01:01', '2021-09-06 12:21:01', 80),
(1002, 9001, '2021-09-06 12:01:01', null, null),
(1002, 9001, '2021-09-07 12:01:01', null, null);
select er.uid,er.exam_id,
round(avg(score),0) avg_score
from exam_record er
join examination_info ei on er.exam_id=ei.exam_id
where tag regexp('^c|^C')
and er.uid in (
select uid
from user_info u
where u.nick_name regexp('^牛客[0-9]+号$|^[0-9]+$')
)
and er.score is not null
group by uid,exam_id
order by uid asc,avg_score asc
select er.uid,er.exam_id,
round(avg(score),0) avg_score
from exam_record er
join examination_info ei on er.exam_id=ei.exam_id
join user_info u on er.uid=u.uid
where tag regexp('^c|^C')
and u.nick_name regexp('^牛客[0-9]+号$|^[0-9]+$')
and er.score is not null
group by uid,exam_id
order by uid asc,avg_score asc
drop table if exists user_info,exam_record;
CREATE TABLE user_info (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int UNIQUE NOT NULL COMMENT '用户ID',
`nick_name` varchar(64) COMMENT '昵称',
achievement int COMMENT '成就值',
level int COMMENT '用户等级',
job varchar(32) COMMENT '职业方向',
register_time datetime COMMENT '注册时间'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE TABLE exam_record (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int NOT NULL COMMENT '用户ID',
exam_id int NOT NULL COMMENT '试卷ID',
start_time datetime NOT NULL COMMENT '开始时间',
submit_time datetime COMMENT '提交时间',
score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
INSERT INTO user_info(uid,`nick_name`,achievement,level,job,register_time) VALUES
(1001, '牛客1', 19, 0, '算法', '2020-01-01 10:00:00'),
(1002, '牛客2号', 1200, 3, '算法', '2020-01-01 10:00:00'),
(1003, '牛客3号♂', 22, 0, '算法', '2020-01-01 10:00:00'),
(1004, '牛客4号', 25, 0, '算法', '2020-01-01 10:00:00'),
(1005, '牛客555号', 2000, 7, 'C++', '2020-01-01 10:00:00'),
(1006, '666666', 3000, 6, 'C++', '2020-01-01 10:00:00');
INSERT INTO exam_record(uid,exam_id,start_time,submit_time,score) VALUES
(1001, 9001, '2020-01-02 09:01:01', '2020-01-02 09:21:59', 80),
(1001, 9001, '2021-05-02 10:01:01', null, null),
(1001, 9002, '2021-02-02 19:01:01', '2021-02-02 19:30:01', 87),
(1001, 9002, '2021-09-01 12:01:01', null, null),
(1001, 9003, '2021-09-02 12:01:01', null, null),
(1001, 9004, '2021-09-03 12:01:01', null, null),
(1002, 9001, '2020-01-01 12:01:01', '2020-01-01 12:31:01', 99),
(1002, 9003, '2020-02-01 12:01:01', '2020-02-01 12:31:01', 82),
(1002, 9003, '2020-02-02 12:11:01', null, null),
(1002, 9002, '2021-05-05 18:01:01', null, null),
(1002, 9001, '2021-09-06 12:01:01', null, null),
(1003, 9003, '2021-02-06 12:01:01', null, null),
(1003, 9001, '2021-09-07 10:01:01', '2021-09-07 10:31:01', 89);
-- 这题需要返回两种情况的结果集
-- 可以在where里面写case表达式
-- 更多的结果集都可以在where里面写case表达式
with tmp as(
select u.uid,
count(case
when start_time is not null and submit_time is not null then 1
else null
end) complete_cnt,
count(case
when start_time is not null and submit_time is null then 1
else null
end) incomplete_cnt
from user_info u
left join exam_record er on er.uid=u.uid
group by u.uid
)
select uid, incomplete_cnt,
round(if(incomplete_cnt/(incomplete_cnt+complete_cnt),incomplete_cnt/(incomplete_cnt+complete_cnt),0),3) incomplete_rate
from tmp
where
CASE
when (
select max(incomplete_cnt) from (
select
count(case
when start_time is not null and submit_time is null then 1
else null
end) incomplete_cnt
from user_info u
left join exam_record er on er.uid=u.uid
where level=0
group by u.uid) t
) > 2 then uid in (select uid from user_info where level=0 )
else uid in (select uid from exam_record)
end
order by incomplete_rate asc
-- 这是大佬写的
with cte as(
select count(start_time)-count(submit_time) as non_0_num
from exam_record
where uid in (select distinct uid from user_info where level=0) )
#计算出0级用户未完成的试卷量
select if((select* from cte)>2,uid in (select distinct uid from user_info where level=0),uid) as uid,
#if(expr,v1,v2)函数,v1中加入uid范围条件,注意不要直接引用cte,然后就是基操了
count(start_time)-count(submit_time) as non_num,
round((count(start_time)-count(submit_time))/count(start_time),3) as non_rate
from exam_record
group by uid
order by non_rate;
drop table if exists user_info,exam_record;
CREATE TABLE user_info (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int UNIQUE NOT NULL COMMENT '用户ID',
`nick_name` varchar(64) COMMENT '昵称',
achievement int COMMENT '成就值',
level int COMMENT '用户等级',
job varchar(32) COMMENT '职业方向',
register_time datetime COMMENT '注册时间'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE TABLE exam_record (
id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',
uid int NOT NULL COMMENT '用户ID',
exam_id int NOT NULL COMMENT '试卷ID',
start_time datetime NOT NULL COMMENT '开始时间',
submit_time datetime COMMENT '提交时间',
score tinyint COMMENT '得分'
)CHARACTER SET utf8 COLLATE utf8_general_ci;
INSERT INTO user_info(uid,`nick_name`,achievement,level,job,register_time) VALUES
(1001, '牛客1', 19, 0, '算法', '2020-01-01 10:00:00'),
(1002, '牛客2号', 1200, 3, '算法', '2020-01-01 10:00:00'),
(1003, '牛客3号♂', 22, 0, '算法', '2020-01-01 10:00:00'),
(1004, '牛客4号', 25, 0, '算法', '2020-01-01 10:00:00'),
(1005, '牛客555号', 2000, 7, 'C++', '2020-01-01 10:00:00'),
(1006, '666666', 3000, 6, 'C++', '2020-01-01 10:00:00');
INSERT INTO exam_record(uid,exam_id,start_time,submit_time,score) VALUES
(1001, 9001, '2020-01-02 09:01:01', '2020-01-02 09:21:59', 80),
(1001, 9001, '2021-05-02 10:01:01', null, null),
(1001, 9002, '2021-02-02 19:01:01', '2021-02-02 19:30:01', 75),
(1001, 9002, '2021-09-01 12:01:01', '2021-09-01 12:11:01', 60),
(1001, 9003, '2021-09-02 12:01:01', '2021-09-02 12:41:01', 90),
(1001, 9001, '2021-06-02 19:01:01', '2021-06-02 19:32:00', 20),
(1001, 9002, '2021-09-05 19:01:01', '2021-09-05 19:40:01', 89),
(1001, 9004, '2021-09-03 12:01:01', null, null),
(1002, 9001, '2020-01-01 12:01:01', '2020-01-01 12:31:01', 99),
(1002, 9003, '2020-02-01 12:01:01', '2020-02-01 12:31:01', 82),
(1002, 9003, '2020-02-02 12:11:01', '2020-02-02 12:41:01', 76);
select u.uid,u.level,er.exam_id,score,
case
when score >= 90 then '优'
when score >=75 and score <90 then '良'
when score >=60 and score <75 then '中'
else '差'
end score_grade
from exam_record er
join user_info u on er.uid=u.uid
where score is not null
![](https://secure2.wostatic.cn/static/xsoyotsnQQbQMQjygvKXBw/image.png)
select u.uid,u.level,er.exam_id,score,
case
when score >= 90 then '优'
when score >=75 and score <90 then '良'
when score >=60 and score <75 then '中'
else '差'
end score_grade,
count(*) over(partition by level) user_part_cnt
from exam_record er
join user_info u on er.uid=u.uid
where score is not null
![](https://secure2.wostatic.cn/static/fb2867V8szLoNj67x6jxDB/image.png)
select
level,score_grade,round(count(score_grade)/user_part_cnt,3) ratio
from (
select u.uid,u.level,er.exam_id,score,
case
when score >= 90 then '优'
when score >=75 and score <90 then '良'
when score >=60 and score <75 then '中'
else '差'
end score_grade,
count(*) over(partition by level) user_part_cnt
from exam_record er
join user_info u on er.uid=u.uid
where score is not null
) t
group by level,score_grade
order by level desc,ratio desc
with t1 as
(select level,
case when score<60 then '差'
when score<75 then '中'
when score<90 then '良'
else '优' end as grade
from exam_record
join user_info
on exam_record.uid=user_info.uid
where score is not null)
select t1.level,t1.grade,round(count(grade)/ct,3) cnt
from t1
join
(select level,count(level) ct
from t1
group by level) t2
on t1.level=t2.level
group by t1.level,t1.grade
order by t1.level desc,cnt desc;
SQL42 注册时间最早的三个人
select
uid, nick_name,register_time
from user_info
order by register_time asc limit 3
select uid, nick_name,register_time from
(
select
uid, nick_name,register_time,
row_number() over( order by register_time) rk
from user_info
) t
where rk <=3
SQL45 对过长的昵称截取处理
select uid,
if(char_length(nick_name)> 13,concat(substr(nick_name,1,10),'...'), nick_name) nick_name
from user_info
where char_length(nick_name) > 10