irpas技术客

牛客刷题-SQL进阶挑战大总结(细节狂魔)_IT邦德_sql 牛客

irpas 4888

📢📢📢📣📣📣 哈喽!大家好,我是【IT邦德】,江湖人称jeames007,10年DBA工作经验 一位上进心十足的【大数据领域博主】!😜😜😜 中国DBA联盟(ACDU)成员,目前从事DBA及程序编程 擅长主流数据Oracle、MySQL、PG 运维开发,备份恢复,安装迁移,性能优化、故障应急处理等。 ? 如果有对【数据库】感兴趣的【小可爱】,欢迎关注【IT邦德】💞💞💞 ??????感谢各位大可爱小可爱!??????

文章目录 前言🐴 1.增删改操作1.1 🌈 插入记录🚀 SQL1 插入记录(一)🚀 SQL2 插入记录(二)🚀 SQL3 插入记录(三) 1.2 🌈 更新记录🚀 SQL4 更新记录(一)🚀 SQL5 更新记录(二) 1.3 🌈 删除记录🚀 SQL6 删除记录(一)🚀 SQL7 删除记录(二)🚀 SQL8 删除记录(三) 🐴 2.表与索引操作2.1 🌈 表的创建、修改与删除🚀 SQL9 创建一张新表🚀 SQL10 修改表🚀 SQL11 删除表 2.2 🌈 索引的创建、删除🚀 SQL12 创建索引🚀 SQL13 删除索引 🐴 3.聚合分组查询3.1 🌈 聚合函数🚀 SQL14 SQL类别高难度试卷得分的截断平均值🚀 SQL15 统计作答次数🚀 SQL16 得分不小于平均分的最低分 3.2 🌈 分组查询🚀 SQL17 平均活跃天数和月活人数🚀 SQL18 月总刷题数和日均刷题数🚀 SQL19 未完成试卷数大于1的有效用户 🐴 4.多表查询4.1 🌈 嵌套子查询🚀 SQL20 月均完成试卷数不小于3的用户爱作答的类别🚀 SQL21 试卷发布当天作答人数和平均分🚀 SQL22 作答试卷得分大于过80的人的用户等级分布 4.2 🌈 合并查询🚀 SQL23 每个题目和每份试卷被作答的人数和次数🚀 SQL24 分别满足两个活动的人 4.3 🌈 连接查询🚀 SQL25 满足条件的用户的试卷完成数和题目练习数🚀 SQL26 每个6/7级用户活跃情况 🐴 5.窗口函数5.1 🌈 专用窗口函数🚀 SQL27 每类试卷得分前3名🚀 SQL28 第二快/慢用时之差大于试卷时长一半的试卷🚀SQL29 连续两次作答试卷的最大时间窗🚀 SQL30 近三个月未完成试卷数为0的用户完成情况🚀 SQL31 未完成率较高的50%用户近三个月答卷情况🚀 SQL32 试卷完成数同比2020年的增长率及排名变化 5.2 🌈 聚合窗口函数🚀 SQL33 对试卷得分做min-max归一化🚀 SQL34 每份试卷每月作答数和截止当月的作答总数🚀 SQL35 每月及截止当月的答题情况

前言 SQL每个人都要用,但是用来衡量产出的并不是SQL本身,你需要用这个工具,去创造其它的价值。
🐴 1.增删改操作 1.1 🌈 插入记录

🚀 SQL1 插入记录(一)

📖 表exam_record结构

🚀 题目描述 牛客后台会记录每个用户的试卷作答记录到exam_record表,现在有两个用户的作答记录详情如下: 用户1001在2021年9月1日晚上10点11分12秒开始作答试卷9001,并在50分钟后提交,得了90分; 用户1002在2021年9月4日上午7点1分2秒开始作答试卷9002,并在10分钟后退出了平台。 试卷作答记录表exam_record中,表已建好,其结构如下,请用一条语句将这两条记录插入表中。 该题最后会通过执行SELECT uid, exam_id, start_time, submit_time, score FROM exam_record; 来对比结果 🚀 建表语句 drop table if EXISTS exam_record; CREATE TABLE IF NOT EXISTS 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; TRUNCATE exam_record; 🍌🍌 答案 insert INTO exam_record values(null,1001,9001,'2021-09-01 22:11:12','2021-09-01 23:01:12',90), (null,1002,9002,'2021-09-04 07:01:02',null,null);

🚀 SQL2 插入记录(二)

📖表exam_record结构

🚀 题目描述 现有一张试卷作答记录表exam_record,其中包含多年来的用户作答试卷记录, 由于数据越来越多,维护难度越来越大,需要对数据表内容做精简,历史数据做备份。 我们已经创建了一张新表exam_record_before_2021用来备份2021年之前的试题作答记录, 结构和exam_record表一致,请将2021年之前的已完成了的试题作答纪录导入到该表。 后台会通过执行"SELECT * FROM exam_record_before_2021;"语句来对比结果 🚀 建表语句 drop table if EXISTS exam_record; CREATE TABLE IF NOT EXISTS 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; CREATE TABLE IF NOT EXISTS exam_record_before_2021 ( 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; TRUNCATE exam_record; TRUNCATE exam_record_before_2021; INSERT INTO exam_record(uid,exam_id,start_time,submit_time,score) VALUES (1001, 9001, '2020-01-01 09:00:01', null, null), (1001, 9002, '2020-01-02 09:01:01', '2020-01-02 09:21:01', 70), (1001, 9002, '2020-09-02 09:00:01', null, null), (1002, 9001, '2021-05-02 10:01:01', '2021-05-02 10:30:01', 81), (1002, 9002, '2021-09-02 12:01:01', null, null); 🍌🍌 答案 INSERT INTO exam_record_before_2021 SELECT NULL,uid, exam_id, start_time, submit_time, score FROM exam_record WHERE submit_time < '2021-01-01 00:00:00';

🚀 SQL3 插入记录(三)

📖 试题信息表examination_info结构

🚀 题目描述 现在有一套ID为9003的高难度SQL试卷,时长为一个半小时, 请你将 2021-01-01 00:00:00 作为发布时间插入到试题信息表examination_info,不管该ID试卷是否存在,都要插入成功,请尝试插入它。 后台会通过执行 SELECT exam_id,tag,difficulty,duration,release_time FROM examination_info 语句来对比结果。 🚀 建表语句 drop table if EXISTS examination_info; CREATE TABLE IF NOT EXISTS 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; TRUNCATE examination_info; INSERT INTO examination_info(exam_id,tag,difficulty,duration,release_time) VALUES (9001, 'SQL', 'hard', 60, '2020-01-01 10:00:00'), (9002, '算法', 'easy', 60, '2020-01-01 10:00:00'), (9003, 'SQL', 'medium', 60, '2020-01-02 10:00:00'), (9004, '算法', 'hard', 80, '2020-01-01 10:00:00'); 🍌🍌 答案 replace into examination_info (id,exam_id,tag,difficulty,duration,release_time) values(null,9003,'SQL','hard',90,'2021-01-01 00:00:00');

1.2 🌈 更新记录 🚀 SQL4 更新记录(一)

📖 现有一张试卷信息表examination_info,表结构如下图所示:

🚀 题目描述 请把examination_info表中tag为PYTHON的tag字段全部修改为Python。 后台会通过执行'SELECT exam_id,tag,difficulty,duration,release_time FROM examination_info;'语句来对比结果。 🚀 建表语句 drop table if EXISTS examination_info; CREATE TABLE IF NOT EXISTS 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; TRUNCATE examination_info; INSERT INTO examination_info(exam_id,tag,difficulty,duration,release_time) VALUES (9001, 'SQL', 'hard', 60, '2020-01-01 10:00:00'), (9002, 'python', 'easy', 60, '2020-01-01 10:00:00'), (9003, 'Python', 'medium', 80, '2020-01-01 10:00:00'), (9004, 'PYTHON', 'hard', 80, '2020-01-01 10:00:00'); 🍌🍌 答案 UPDATE examination_info set tag ='Python' WHERE tag='PYTHON';

🚀 SQL5 更新记录(二)

📖 作答记录表exam_record表结构

🚀 题目描述 现有一张试卷作答记录表exam_record,其中包含多年来的用户作答试卷记录,submit_time为 完成时间 请把exam_record表中2021年9月1日之前开始作答的未完成记录全部改为被动完成, 即:将完成时间改为'2099-01-01 00:00:00',分数改为0。 🚀 建表语句 drop table if EXISTS exam_record; CREATE TABLE IF NOT EXISTS 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, 9002, '2021-09-01 09:01:01', '2021-09-01 09:21:01', 90), (1002, 9001, '2021-08-02 19:01:01', null, null), (1002, 9002, '2021-09-05 19:01:01', '2021-09-05 19:40:01', 89), (1003, 9001, '2021-09-02 12:01:01', null, null), (1003, 9002, '2021-09-01 12:01:01', null, null); 🍌🍌 答案 UPDATE exam_record set submit_time='2099-01-01 00:00:00', score=0 WHERE start_time<'2021-09-01' and submit_time is null;

1.3 🌈 删除记录 🚀 SQL6 删除记录(一)

📖 作答记录表exam_record表结构,start_time是试卷开始时间,submit_time 是交卷,即结束时间

🚀 题目描述 现有一张试卷作答记录表exam_record,其中包含多年来的用户作答试卷记录, start_time是试卷开始时间 submit_time 是交卷,即结束时间 请删除exam_record表中作答时间小于5分钟整且分数不及格(及格线为60分)的记录; 后台会执行您的SQL,然后通过 SELECT * FROM exam_record; 语句来筛选出剩下的数据,与正确数据进行对比。 🚀 建表语句 drop table if EXISTS exam_record; CREATE TABLE IF NOT EXISTS 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; TRUNCATE exam_record; INSERT INTO exam_record(uid, exam_id, start_time, submit_time, score) VALUES (1001, 9001, '2020-01-01 22:11:12', '2020-01-01 23:16:12', 50), (1001, 9002, '2020-01-02 09:01:01', '2020-01-02 09:06:00', 58), (1002, 9001, '2021-05-02 10:01:01', '2021-05-02 10:05:58', 60), (1002, 9002, '2021-06-02 19:01:01', '2021-06-02 19:05:01', 54), (1003, 9001, '2021-09-05 19:01:01', '2021-09-05 19:40:01', 49), (1003, 9001, '2021-09-05 19:01:01', '2021-09-05 19:15:01', 70), (1003, 9001, '2021-09-06 19:01:01', '2021-09-06 19:05:01', 80), (1003, 9002, '2021-09-09 07:01:02', null, null); 🍌🍌 答案 delete from exam_record where timestampdiff(minute,start_time,submit_time) < 5 and score < 60;

🚀 SQL7 删除记录(二)

📖 作答记录表exam_record结构如下:

🚀 题目描述 现有一张试卷作答记录表exam_record,其中包含多年来的用户作答试卷记录,start_time是试卷开始时间 submit_time 是交卷时间,即结束时间,如果未完成的话,则为空 请删除exam_record表中未完成作答或作答时间小于5分钟整的记录中,开始作答时间最早的3条记录。 后台会通过 SELECT * FROM exam_record 语句来对比结果。 🚀 建表语句 drop table if EXISTS exam_record; CREATE TABLE IF NOT EXISTS 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; TRUNCATE exam_record; INSERT INTO exam_record(uid, exam_id, start_time, submit_time, score) VALUES (1001, 9001, '2020-01-01 22:11:12', '2020-01-01 23:16:12', 50), (1001, 9002, '2020-01-02 09:01:01', '2020-01-02 09:06:00', 58), (1001, 9002, '2020-01-02 09:01:01', '2020-01-02 09:05:01', 58), (1002, 9001, '2021-05-02 10:01:01', '2021-05-02 10:06:58', 60), (1002, 9002, '2021-06-02 19:01:01', null, null), (1003, 9001, '2021-09-05 19:01:01', null, null), (1003, 9001, '2021-09-05 19:01:01', null, null), (1003, 9002, '2021-09-09 07:01:02', null, null); 🍌🍌 答案 delete from exam_record where timestampdiff(minute, start_time, submit_time) < 5 or submit_time is null order by start_time limit 3;

🚀 SQL8 删除记录(三)

📖 试卷作答记录表exam_record表结构

🚀 题目描述 现有一张试卷作答记录表exam_record,其中包含多年来的用户作答试卷记录, 请删除exam_record表中所有记录,并重置自增主键。 后台会通过SELECT table_rows, auto_increment FROM information_schema.tables WHERE table_name='exam_record'语句来对比输出结果 🚀 建表语句 drop table if EXISTS exam_record; CREATE TABLE IF NOT EXISTS 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; TRUNCATE exam_record; INSERT INTO exam_record(uid, exam_id, start_time, submit_time, score) VALUES (1001, 9001, '2020-01-01 22:11:12', '2020-01-01 23:16:12', 50), (1001, 9002, '2020-01-02 09:01:01', '2020-01-02 09:06:00', 58); 🍌🍌 答案 TRUNCATE table exam_record;

🐴 2.表与索引操作 2.1 🌈 表的创建、修改与删除 🚀 SQL9 创建一张新表

📖 原来的用户信息表

🚀 题目描述 现有一张用户信息表,其中包含多年来在平台注册过的用户信息,随着牛客平台的不断壮大, 用户量飞速增长,为了高效地为高活跃用户提供服务,现需要将部分用户拆分出一张新表。 作为数据分析师,请创建一张优质用户信息表user_info_vip,表结构和用户信息表一致。 请写出建表语句将表格中所有限制和说明记录到表里。 备注: 1.后台会通过 SHOW FULL FIELDS FROM user_info_vip 语句,来对比输出结果 2.如果该表已经被其他分析师创建过了,正常返回即可 🍌🍌 答案 create table if not exists user_info_vip ( id int(11) primary key auto_increment comment '自增ID', uid int(11) unique not null comment '用户ID', nick_name varchar(64) comment '昵称', achievement int(11) default 0 comment '成就值', level int(11) comment '用户等级', job varchar(32) comment '职业方向', register_time datetime default current_timestamp comment '注册时间' );

🚀 SQL10 修改表

📖 用户信息表user_info

🚀 题目描述 现有一张用户信息表user_info,其中包含多年来在平台注册过的用户信息。 请在用户信息表,字段level的后面增加一列最多可保存15个汉字的字段school; 并将表中job列名改为profession,同时varchar字段长度变为10; achievement的默认值设置为0。 备注:建表时限制的字符集为utf8,MySQL版本为8.* 后台会通过SHOW FULL FIELDS FROM user_info 来对比输出结果。 🚀 建表语句 drop table if exists user_info; CREATE TABLE IF NOT EXISTS 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(10) COMMENT '职业方向', register_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT '注册时间' )CHARACTER SET utf8 COLLATE utf8_general_ci; 🍌🍌 答案 ALTER TABLE user_info ADD school varchar(15) after level; ALTER TABLE user_info CHANGE job profession varchar(10); ALTER TABLE user_info modify achievement int(11) DEFAULT 0;

🚀 SQL11 删除表 🚀 题目描述 现有一张试卷作答记录表exam_record,其中包含多年来的用户作答试卷记录。 一般每年都会为exam_record表建立一张备份表exam_record_{YEAR},{YEAR}为对应年份。 现在随着数据越来越多,存储告急,请你把很久前的(2011到2014年)备份表都删掉(如果存在的话)。 备注:后台会通过SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_NAME LIKE \'exam\_record\_201_\' 来对比输出结果。 🚀 建表语句 drop table if EXISTS exam_record; CREATE TABLE IF NOT EXISTS 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; CREATE TABLE IF NOT EXISTS exam_record_2010 (LIKE exam_record); CREATE TABLE IF NOT EXISTS exam_record_2012 (LIKE exam_record); CREATE TABLE IF NOT EXISTS exam_record_2013 (LIKE exam_record); CREATE TABLE IF NOT EXISTS exam_record_2014 (LIKE exam_record); CREATE TABLE IF NOT EXISTS exam_record_2015 (LIKE exam_record); 🍌🍌 答案 drop table if exists exam_record_2011, exam_record_2012, exam_record_2013, exam_record_2014;

2.2 🌈 索引的创建、删除

🚀 SQL12 创建索引

📖 根据题意,将返回如下结果:

🚀 题目描述 现有一张试卷信息表examination_info,其中包含各种类型试卷的信息。为了对表更方便快捷地查询, 需要在examination_info表创建以下索引,规则如下: 在duration列创建普通索引idx_duration、在exam_id列创建唯一性索引uniq_idx_exam_id、在tag列创建全文索引full_idx_tag。 🚀 建表语句 drop table if exists examination_info; CREATE TABLE IF NOT EXISTS 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; 🍌🍌 答案 -- 唯一索引 ALTER TABLE examination_info ADD UNIQUE INDEX uniq_idx_exam_id(exam_id); -- 全文索引 ALTER TABLE examination_info ADD FULLTEXT INDEX full_idx_tag(tag); -- 普通索引 ALTER TABLE examination_info ADD INDEX idx_duration(duration);

🚀 SQL13 删除索引 🚀 题目描述 请删除examination_info表上的唯一索引uniq_idx_exam_id和全文索引full_idx_tag。 后台会通过 SHOW INDEX FROM examination_info 来对比输出结果。 🚀 建表语句 drop table if exists examination_info; CREATE TABLE IF NOT EXISTS examination_info ( id int PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID', exam_id int 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 INDEX idx_duration ON examination_info(duration); CREATE UNIQUE INDEX uniq_idx_exam_id ON examination_info(exam_id); ALTER TABLE examination_info ADD FULLTEXT full_idx_tag(tag); 🍌🍌 答案 drop index uniq_idx_exam_id on examination_info; drop index full_idx_tag on examination_info;

🐴 3.聚合分组查询 3.1 🌈 聚合函数 🚀 SQL14 SQL类别高难度试卷得分的截断平均值

📖 examination_info表结构 📖 exam_record表结构

🚀 题目描述 牛客的运营同学想要查看大家在SQL类别中高难度试卷的得分情况。 请你帮她从exam_record数据表中计算所有用户完成SQL类别高难度试卷得分的截断平均值(去掉一个最大值和一个最小值后的平均值) 示例数据:examination_info(exam_id试卷ID, tag试卷类别, difficulty试卷难度, duration考试时长, release_time发布时间) +----+---------+--------+------------+----------+---------------------+ | id | exam_id | tag | difficulty | duration | release_time | +----+---------+--------+------------+----------+---------------------+ | 1 | 9001 | SQL | hard | 60 | 2020-01-01 10:00:00 | | 2 | 9002 | 算法 | medium | 80 | 2020-08-02 10:00:00 | +----+---------+--------+------------+----------+---------------------+ 示例数据:exam_record(uid用户ID, exam_id试卷ID, start_time开始作答时间, submit_time交卷时间, score得分) +----+------+---------+---------------------+---------------------+-------+ | id | uid | exam_id | start_time | submit_time | score | +----+------+---------+---------------------+---------------------+-------+ | 1 | 1001 | 9001 | 2020-01-02 09:01:01 | 2020-01-02 09:21:01 | 80 | | 2 | 1001 | 9001 | 2021-05-02 10:01:01 | 2021-05-02 10:30:01 | 81 | | 3 | 1001 | 9001 | 2021-06-02 19:01:01 | 2021-06-02 19:31:01 | 84 | | 4 | 1001 | 9002 | 2021-09-05 19:01:01 | 2021-09-05 19:40:01 | 89 | | 5 | 1001 | 9001 | 2021-09-02 12:01:01 | NULL | NULL | | 6 | 1001 | 9002 | 2021-09-01 12:01:01 | NULL | NULL | | 7 | 1002 | 9002 | 2021-02-02 19:01:01 | 2021-02-02 19:30:01 | 87 | | 8 | 1002 | 9001 | 2021-05-05 18:01:01 | 2021-05-05 18:59:02 | 90 | | 9 | 1003 | 9001 | 2021-02-06 12:01:01 | NULL | NULL | | 10 | 1003 | 9001 | 2021-09-07 10:01:01 | 2021-09-07 10:31:01 | 50 | +----+------+---------+---------------------+---------------------+-------+ 从examination_info表可知,试卷9001为高难度SQL试卷,该试卷被作答的得分有[80,81,84,90,50], 去除最高分和最低分后为[80,81,84],平均分为81.6666667,保留一位小数后为81.7 根据输入你的查询结果如下: +------+------------+-----------+ | tag | difficulty | avg_score | +------+------------+-----------+ | SQL | hard | 81.7 | +------+------------+-----------+ 🚀 建表语句 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); 🍌🍌 答案 select tag,difficulty, round((sum(score)-min(score)-max(score))/ (count(score)-2),1) as avg_score from examination_info join exam_record using(exam_id) where tag='SQL' and difficulty='hard';

🚀 SQL15 统计作答次数

📖 exam_record表结构

🚀 题目描述 有一个试卷作答记录表exam_record,请从中统计出总作答次数total_pv、试卷已完成作答数complete_pv、已完成的试卷数complete_exam_cnt。 示例数据 exam_record表(uid用户ID, exam_id试卷ID, start_time开始作答时间, submit_time交卷时间, score得分): +----+------+---------+---------------------+---------------------+-------+ | id | uid | exam_id | start_time | submit_time | score | +----+------+---------+---------------------+---------------------+-------+ | 1 | 1001 | 9001 | 2020-01-02 09:01:01 | 2020-01-02 09:21:01 | 80 | | 2 | 1001 | 9001 | 2021-05-02 10:01:01 | 2021-05-02 10:30:01 | 81 | | 3 | 1001 | 9001 | 2021-06-02 19:01:01 | 2021-06-02 19:31:01 | 84 | | 4 | 1001 | 9002 | 2021-09-05 19:01:01 | 2021-09-05 19:40:01 | 89 | | 5 | 1001 | 9001 | 2021-09-02 12:01:01 | NULL | NULL | | 6 | 1001 | 9002 | 2021-09-01 12:01:01 | NULL | NULL | | 7 | 1002 | 9002 | 2021-02-02 19:01:01 | 2021-02-02 19:30:01 | 87 | | 8 | 1002 | 9001 | 2021-05-05 18:01:01 | 2021-05-05 18:59:02 | 90 | | 9 | 1003 | 9001 | 2021-02-06 12:01:01 | NULL | NULL | | 10 | 1003 | 9001 | 2021-09-07 10:01:01 | 2021-09-07 10:31:01 | 89 | | 11 | 1004 | 9001 | 2021-09-06 12:01:01 | NULL | NULL | +----+------+---------+---------------------+---------------------+-------+ 示例输出: +----------+--------------+-------------------+ | total_pv | compelete_pv | complete_exam_cnt | +----------+--------------+-------------------+ | 11 | 7 | 2 | +----------+--------------+-------------------+ 解释:表示截止当前,有11次试卷作答记录,已完成的作答次数为7次(中途退出的为未完成状态,其交卷时间和份数为NULL), 已完成的试卷有9001和9002两份。 🚀 建表语句 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); 🍌🍌 答案 select DISTINCT count(*) as total_pv, count(submit_time) as compelete_pv, count(distinct exam_id and score IS not NULL) as complete_exam_cnt from exam_record;

🚀 SQL16 得分不小于平均分的最低分

📖 examination_info表结构 📖 exam_record表结构

🚀 题目描述 请从试卷作答记录表中找到SQL试卷得分不小于该类试卷平均得分的用户最低得分。 示例数据 exam_record表(uid用户ID, exam_id试卷ID, start_time开始作答时间, submit_time交卷时间, score得分): +----+------+---------+---------------------+---------------------+-------+ | id | uid | exam_id | start_time | submit_time | score | +----+------+---------+---------------------+---------------------+-------+ | 1 | 1001 | 9001 | 2020-01-02 09:01:01 | 2020-01-02 09:21:01 | 80 | | 2 | 1002 | 9001 | 2021-09-05 19:01:01 | 2021-09-05 19:40:01 | 89 | | 3 | 1002 | 9002 | 2021-09-02 12:01:01 | NULL | NULL | | 4 | 1002 | 9003 | 2021-09-01 12:01:01 | NULL | NULL | | 5 | 1002 | 9001 | 2021-02-02 19:01:01 | 2021-02-02 19:30:01 | 87 | | 6 | 1002 | 9002 | 2021-05-05 18:01:01 | 2021-05-05 18:59:02 | 90 | | 7 | 1003 | 9002 | 2021-02-06 12:01:01 | NULL | NULL | | 8 | 1003 | 9003 | 2021-09-07 10:01:01 | 2021-09-07 10:31:01 | 86 | | 9 | 1004 | 9003 | 2021-09-06 12:01:01 | NULL | NULL | +----+------+---------+---------------------+---------------------+-------+ examination_info表(exam_id试卷ID, tag试卷类别, difficulty试卷难度, duration考试时长, release_time发布时间) +----+---------+--------+------------+----------+---------------------+ | id | exam_id | tag | difficulty | duration | release_time | +----+---------+--------+------------+----------+---------------------+ | 1 | 9001 | SQL | hard | 60 | 2020-01-01 10:00:00 | | 2 | 9002 | SQL | easy | 60 | 2020-02-01 10:00:00 | | 3 | 9003 | 算法 | medium | 80 | 2020-08-02 10:00:00 | +----+---------+--------+------------+----------+---------------------+ 示例输出数据: +--------------------+ | min_score_over_avg | +--------------------+ | 87 | +--------------------+ 保证至少有一个有效的SQL类别的试卷作答分数 解释:试卷9001和9002为SQL类别,作答这两份试卷的得分有[80,89,87,90],平均分为86.5,不小于平均分的最小分数为87 🚀 建表语句 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) as min_score_over_avg from examination_info as i join exam_record as r on i.exam_id = r.exam_id where tag = 'SQL' and score >= (select avg(score) from examination_info as i join exam_record as r on i.exam_id = r.exam_id where tag = 'SQL');

3.2 🌈 分组查询

🚀 SQL17 平均活跃天数和月活人数

📖 exam_record表结构

🚀 题目描述 用户在牛客试卷作答区作答记录存储在表exam_record中,内容如下: exam_record表(uid用户ID, exam_id试卷ID, start_time开始作答时间, submit_time交卷时间, score得分) +----+------+---------+---------------------+---------------------+-------+ | id | uid | exam_id | start_time | submit_time | score | +----+------+---------+---------------------+---------------------+-------+ | 1 | 1001 | 9001 | 2021-07-02 09:01:01 | 2021-07-02 09:21:01 | 80 | | 2 | 1002 | 9001 | 2021-09-05 19:01:01 | 2021-09-05 19:40:01 | 81 | | 3 | 1002 | 9002 | 2021-09-02 12:01:01 | NULL | NULL | | 4 | 1002 | 9003 | 2021-09-01 12:01:01 | NULL | NULL | | 5 | 1002 | 9001 | 2021-07-02 19:01:01 | 2021-07-02 19:30:01 | 82 | | 6 | 1002 | 9002 | 2021-07-05 18:01:01 | 2021-07-05 18:59:02 | 90 | | 7 | 1003 | 9002 | 2021-07-06 12:01:01 | NULL | NULL | | 8 | 1003 | 9003 | 2021-09-07 10:01:01 | 2021-09-07 10:31:01 | 86 | | 9 | 1004 | 9003 | 2021-09-06 12:01:01 | NULL | NULL | | 10 | 1002 | 9003 | 2021-09-01 12:01:01 | 2021-09-01 12:31:01 | 81 | | 11 | 1005 | 9001 | 2021-09-01 12:01:01 | 2021-09-01 12:31:01 | 88 | | 12 | 1006 | 9002 | 2021-09-02 12:11:01 | 2021-09-02 12:31:01 | 89 | | 13 | 1007 | 9002 | 2020-09-02 12:11:01 | 2020-09-02 12:31:01 | 89 | +----+------+---------+---------------------+---------------------+-------+ 请计算2021年每个月里试卷作答区用户平均月活跃天数avg_active_days和月度活跃人数mau,上面数据的示例输出如下: +--------+-----------------+-----+ | month | avg_active_days | mau | +--------+-----------------+-----+ | 202107 | 1.50 | 2 | | 202109 | 1.25 | 4 | +--------+-----------------+-----+ 解释:2021年7月有2人活跃,共活跃了3天(1001活跃1天,1002活跃2天),平均活跃天数1.5; 2021年9月有4人活跃,共活跃了5天,平均活跃天数1.25,结果保留2位小数。 注:此处活跃指有交卷行为。 🚀 建表语句 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), (1007, 9002, '2020-09-02 12:11:01', '2020-09-02 12:31:01', 89); 🍌🍌 答案 select concat(substr(submit_time,1,4),substr(submit_time,6,2)) as month , round(count(distinct uid, day(submit_time))/count(distinct uid),2) as avg_active_days , round(count(distinct(uid)),0) as mau from exam_record where submit_time is not null and year(submit_time) ='2021' group by month;

🚀 SQL18 月总刷题数和日均刷题数

📖 practice_record表结构

🚀 题目描述 现有一张题目练习记录表practice_record,示例内容如下: +----+------+-------------+---------------------+-------+ | id | uid | question_id | submit_time | score | +----+------+-------------+---------------------+-------+ | 1 | 1001 | 8001 | 2021-08-02 11:41:01 | 60 | | 2 | 1002 | 8001 | 2021-09-02 19:30:01 | 50 | | 3 | 1002 | 8001 | 2021-09-02 19:20:01 | 70 | | 4 | 1002 | 8002 | 2021-09-02 19:38:01 | 70 | | 5 | 1003 | 8002 | 2021-08-01 19:38:01 | 80 | +----+------+-------------+---------------------+-------+ 请从中统计出2021年每个月里用户的月总刷题数month_q_cnt 和日均刷题数avg_day_q_cnt(按月份升序排序)以及该年的总体情况,示例数据输出如下: +--------------+-------------+---------------+ | submit_month | month_q_cnt | avg_day_q_cnt | +--------------+-------------+---------------+ | 202108 | 2 | 0.065 | | 202109 | 3 | 0.100 | | 2021汇总 | 5 | 0.161 | +--------------+-------------+---------------+ 解释:2021年8月共有2次刷题记录,日均刷题数为2/31=0.065(保留3位小数); 2021年9月共有3次刷题记录,日均刷题数为3/30=0.100; 2021年共有5次刷题记录(年度汇总平均无实际意义,这里我们按照31天来算5/31=0.161) 🚀 建表语句 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); 🍌🍌 答案 SELECT IFNULL(sm, "2021汇总") submit_month , COUNT(question_id) month_q_cnt , ROUND(COUNT(question_id) / MAX(DAY(LAST_DAY(submit_time))),3) avg_day_q_cnt FROM (SELECT *, DATE_FORMAT(submit_time, "%Y%m") sm FROM practice_record) t1 WHERE YEAR(submit_time) = 2021 GROUP BY sm WITH ROLLUP ORDER BY submit_month;

🚀 SQL19 未完成试卷数大于1的有效用户

📖 examination_info表结构 📖 practice_record表结构

🚀 题目描述 现有试卷作答记录表exam_record(uid用户ID, exam_id试卷ID, start_time开始作答时间, submit_time交卷时间, score得分),示例数据如下: +----+------+---------+---------------------+---------------------+-------+ | id | uid | exam_id | start_time | submit_time | score | +----+------+---------+---------------------+---------------------+-------+ | 1 | 1001 | 9001 | 2021-07-02 09:01:01 | 2021-07-02 09:21:01 | 80 | | 2 | 1002 | 9001 | 2021-09-05 19:01:01 | 2021-09-05 19:40:01 | 81 | | 3 | 1002 | 9002 | 2021-09-02 12:01:01 | NULL | NULL | | 4 | 1002 | 9003 | 2021-09-01 12:01:01 | NULL | NULL | | 5 | 1002 | 9001 | 2021-07-02 19:01:01 | 2021-07-02 19:30:01 | 82 | | 6 | 1002 | 9002 | 2021-07-05 18:01:01 | 2021-07-05 18:59:02 | 90 | | 7 | 1003 | 9002 | 2021-07-06 12:01:01 | NULL | NULL | | 8 | 1003 | 9003 | 2021-09-07 10:01:01 | 2021-09-07 10:31:01 | 86 | | 9 | 1004 | 9003 | 2021-09-06 12:01:01 | NULL | NULL | | 10 | 1002 | 9003 | 2021-09-01 12:01:01 | 2021-09-01 12:31:01 | 81 | | 11 | 1005 | 9001 | 2021-09-01 12:01:01 | 2021-09-01 12:31:01 | 88 | | 12 | 1005 | 9002 | 2021-09-01 12:01:01 | 2021-09-01 12:31:01 | 88 | | 13 | 1006 | 9002 | 2021-09-02 12:11:01 | 2021-09-02 12:31:01 | 89 | +----+------+---------+---------------------+---------------------+-------+ 还有一张试卷信息表examination_info(exam_id试卷ID, tag试卷类别, difficulty试卷难度, duration考试时长, release_time发布时间),示例数据如下: +----+---------+--------+------------+----------+---------------------+ | id | exam_id | tag | difficulty | duration | release_time | +----+---------+--------+------------+----------+---------------------+ | 1 | 9001 | SQL | hard | 60 | 2020-01-01 10:00:00 | | 2 | 9002 | SQL | easy | 60 | 2020-02-01 10:00:00 | | 3 | 9003 | 算法 | medium | 80 | 2020-08-02 10:00:00 | +----+---------+--------+------------+----------+---------------------+ 请统计2021年每个未完成试卷作答数大于1的有效用户的数据(有效用户指完成试卷作答数至少为1且未完成数小于5), 输出用户ID、未完成试卷作答数、完成试卷作答数、作答过的试卷tag集合,按未完成试卷数量由多到少排序。示例数据的输出结果如下: +------+----------------+--------------+-------------------------------------------------------------------------------+ | uid | incomplete_cnt | complete_cnt | detail | +------+----------------+--------------+-------------------------------------------------------------------------------+ | 1002 | 2 | 4 | 2021-07-02:SQL;2021-07-05:SQL;2021-09-01:算法;2021-09-02:SQL;2021-09-05:SQL | +------+----------------+--------------+-------------------------------------------------------------------------------+ 解释:2021年的作答记录中,除了1004,其他用户均满足有效用户定义,但只有1002未完成试卷数大于1, 因此只输出1002,detail中是1002作答过的试卷{日期:tag}集合,日期和tag间用:连接,多元素间用;连接。 🚀 建表语句 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, count(incomplete) as incomplete_cnt, count(complete) as complete_cnt, group_concat(distinct concat_ws(':', date(start_time), tag) SEPARATOR ';') as detail from ( SELECT uid, tag, start_time, if(submit_time is null, 1, null) as incomplete, if(submit_time is null, null, 1) as complete from exam_record left join examination_info using(exam_id) where year(start_time)=2021 ) as exam_complete_rec group by uid having complete_cnt >= 1 and incomplete_cnt BETWEEN 2 and 4 order by incomplete_cnt DESC;

🐴 4.多表查询

4.1 🌈 嵌套子查询 🚀 SQL20 月均完成试卷数不小于3的用户爱作答的类别

📖 examination_info表结构 📖 exam_record表结构

🚀 题目描述 现有试卷作答记录表exam_record(uid:用户ID, exam_id:试卷ID, start_time:开始作答时间, submit_time:交卷时间,没提交的话为NULL, score:得分),示例数据如下: +----+------+---------+---------------------+---------------------+-------+ | id | uid | exam_id | start_time | submit_time | score | +----+------+---------+---------------------+---------------------+-------+ | 1 | 1001 | 9001 | 2021-07-02 09:01:01 | NULL | NULL | | 2 | 1002 | 9003 | 2021-09-01 12:01:01 | 2021-09-01 12:21:01 | 60 | | 3 | 1002 | 9002 | 2021-09-02 12:01:01 | 2021-09-02 12:31:01 | 70 | | 4 | 1002 | 9001 | 2021-09-05 19:01:01 | 2021-09-05 19:40:01 | 81 | | 5 | 1002 | 9002 | 2021-07-06 12:01:01 | NULL | NULL | | 6 | 1003 | 9003 | 2021-09-07 10:01:01 | 2021-09-07 10:31:01 | 86 | | 7 | 1003 | 9003 | 2021-09-08 12:01:01 | 2021-09-08 12:11:01 | 40 | | 8 | 1003 | 9001 | 2021-09-08 13:01:01 | NULL | NULL | | 9 | 1003 | 9002 | 2021-09-08 14:01:01 | NULL | NULL | | 10 | 1003 | 9003 | 2021-09-08 15:01:01 | NULL | NULL | | 11 | 1005 | 9001 | 2021-09-01 12:01:01 | 2021-09-01 12:31:01 | 88 | | 12 | 1005 | 9002 | 2021-09-01 12:01:01 | 2021-09-01 12:31:01 | 88 | | 13 | 1005 | 9002 | 2021-09-02 12:11:01 | 2021-09-02 12:31:01 | 89 | +----+------+---------+---------------------+---------------------+-------+ 试卷信息表examination_info(exam_id:试卷ID, tag:试卷类别, difficulty:试卷难度, duration:考试时长, release_time:发布时间), 示例数据如下: +----+---------+--------+------------+----------+---------------------+ | id | exam_id | tag | difficulty | duration | release_time | +----+---------+--------+------------+----------+---------------------+ | 1 | 9001 | SQL | hard | 60 | 2020-01-01 10:00:00 | | 2 | 9002 | C++ | easy | 60 | 2020-02-01 10:00:00 | | 3 | 9003 | 算法 | medium | 80 | 2020-08-02 10:00:00 | +----+---------+--------+------------+----------+---------------------+ 请从表中统计出 “当月均完成试卷数”不小于3的用户们爱作答的类别及作答次数,按次数降序输出,示例输出如下: 解释:用户1002和1005在2021年09月的完成试卷数目均为3,其他用户均小于3; 然后用户1002和1005作答过的试卷tag分布结果按作答次数降序排序依次为C++、SQL、算法。 🚀 建表语句 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 tag, count(start_time) as tag_cnt from exam_record er inner join examination_info ei on er.exam_id = ei.exam_id where uid in (select uid from exam_record er group by uid, month(start_time) having count(submit_time) >= 3) group by tag order by tag_cnt desc;

🚀 SQL21 试卷发布当天作答人数和平均分

📖 user_info表结构 📖 examination_info表结构 📖 exam_record表结构

🚀 题目描述 现有用户信息表user_info(uid用户ID,nick_name昵称, achievement成就值, level等级, job职业方向, register_time注册时间),示例数据如下: +----+------+------------+-------------+-------+--------+---------------------+ | id | uid | nick_name | achievement | level | job | register_time | +----+------+------------+-------------+-------+--------+---------------------+ | 1 | 1001 | 牛客1号 | 3100 | 7 | 算法 | 2020-01-01 10:00:00 | | 2 | 1002 | 牛客2号 | 2100 | 6 | 算法 | 2020-01-01 10:00:00 | | 3 | 1003 | 牛客3号 | 1500 | 5 | 算法 | 2020-01-01 10:00:00 | | 4 | 1004 | 牛客4号 | 1100 | 4 | 算法 | 2020-01-01 10:00:00 | | 5 | 1005 | 牛客5号 | 1600 | 6 | C++ | 2020-01-01 10:00:00 | | 6 | 1006 | 牛客6号 | 3000 | 6 | C++ | 2020-01-01 10:00:00 | +----+------+------------+-------------+-------+--------+---------------------+ 释义:用户1001昵称为牛客1号,成就值为3100,用户等级是7级,职业方向为算法,注册时间2020-01-01 10:00:00 试卷信息表examination_info(exam_id试卷ID, tag试卷类别, difficulty试卷难度, duration考试时长, release_time发布时间) 示例数据如下: +----+---------+--------+------------+----------+---------------------+ | id | exam_id | tag | difficulty | duration | release_time | +----+---------+--------+------------+----------+---------------------+ | 1 | 9001 | SQL | hard | 60 | 2021-09-01 06:00:00 | | 2 | 9002 | C++ | easy | 60 | 2020-02-01 10:00:00 | | 3 | 9003 | 算法 | medium | 80 | 2020-08-02 10:00:00 | +----+---------+--------+------------+----------+---------------------+ 试卷作答记录表exam_record(uid用户ID, exam_id试卷ID, start_time开始作答时间, submit_time交卷时间, score得分) 示例数据如下: +----+------+---------+---------------------+---------------------+-------+ | id | uid | exam_id | start_time | submit_time | score | +----+------+---------+---------------------+---------------------+-------+ | 1 | 1001 | 9001 | 2021-09-01 09:01:01 | 2021-09-01 09:41:01 | 70 | | 2 | 1002 | 9003 | 2021-09-01 12:01:01 | 2021-09-01 12:21:01 | 60 | | 3 | 1002 | 9002 | 2021-09-02 12:01:01 | 2021-09-02 12:31:01 | 70 | | 4 | 1002 | 9001 | 2021-09-01 19:01:01 | 2021-09-01 19:40:01 | 80 | | 5 | 1002 | 9003 | 2021-08-01 12:01:01 | 2021-08-01 12:21:01 | 60 | | 6 | 1002 | 9002 | 2021-08-02 12:01:01 | 2021-08-02 12:31:01 | 70 | | 7 | 1002 | 9001 | 2021-09-01 19:01:01 | 2021-09-01 19:40:01 | 85 | | 8 | 1002 | 9002 | 2021-07-06 12:01:01 | NULL | NULL | | 9 | 1003 | 9003 | 2021-09-07 10:01:01 | 2021-09-07 10:31:01 | 86 | | 10 | 1003 | 9003 | 2021-09-08 12:01:01 | 2021-09-08 12:11:01 | 40 | | 11 | 1003 | 9001 | 2021-09-01 13:01:01 | 2021-09-01 13:41:01 | 70 | | 12 | 1003 | 9002 | 2021-09-08 14:01:01 | NULL | NULL | | 13 | 1003 | 9003 | 2021-09-08 15:01:01 | NULL | NULL | | 14 | 1005 | 9001 | 2021-09-01 12:01:01 | 2021-09-01 12:31:01 | 90 | | 15 | 1005 | 9002 | 2021-09-01 12:01:01 | 2021-09-01 12:31:01 | 88 | | 16 | 1005 | 9002 | 2021-09-02 12:11:01 | 2021-09-02 12:31:01 | 89 | +----+------+---------+---------------------+---------------------+-------+ 请计算每张SQL类别试卷发布后,当天5级以上的用户作答的人数uv和平均分avg_score,按人数降序,相同人数的按平均分升序,示例数据结果输出如下: +---------+----+-----------+ | exam_id | uv | avg_score | +---------+----+-----------+ | 9001 | 3 | 81.3 | +---------+----+-----------+ 解释:只有一张SQL类别的试卷,试卷ID为9001,发布当天(2021-09-01)有1001、1002、1003、1005作答过, 但是1003是5级用户,其他3位为5级以上,他们三的得分有[70,80,85,90],平均分为81.3(保留1位小数)。 🚀 建表语句 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 exam_id, count( DISTINCT uid ) AS uv, ROUND(avg( score ), 1) AS avg_score FROM exam_record WHERE (exam_id, DATE(start_time)) IN ( SELECT exam_id, DATE(release_time) FROM examination_info WHERE tag = "SQL" ) AND uid IN ( SELECT uid FROM user_info WHERE `level` > 5 ) GROUP BY exam_id ORDER BY uv DESC, avg_score ASC; 备注: 结果按人数uv降序,相同人数的按平均分升序

🚀 SQL22 作答试卷得分大于过80的人的用户等级分布

📖 user_info表结构 📖 examination_info表结构 📖 exam_record表结构

🚀 题目描述 现有用户信息表user_info(uid用户ID,nick_name昵称, achievement成就值, level等级, job职业方向, register_time注册时间),示例数据如下: +----+------+------------+-------------+-------+--------+---------------------+ | id | uid | nick_name | achievement | level | job | register_time | +----+------+------------+-------------+-------+--------+---------------------+ | 1 | 1001 | 牛客1号 | 3100 | 7 | 算法 | 2020-01-01 10:00:00 | | 2 | 1002 | 牛客2号 | 2100 | 6 | 算法 | 2020-01-01 10:00:00 | | 3 | 1003 | 牛客3号 | 1500 | 5 | 算法 | 2020-01-01 10:00:00 | | 4 | 1004 | 牛客4号 | 1100 | 4 | 算法 | 2020-01-01 10:00:00 | | 5 | 1005 | 牛客5号 | 1600 | 6 | C++ | 2020-01-01 10:00:00 | | 6 | 1006 | 牛客6号 | 3000 | 6 | C++ | 2020-01-01 10:00:00 | +----+------+------------+-------------+-------+--------+---------------------+ 释义:用户1001昵称为牛客1号,成就值为3100,用户等级是7级,职业方向为算法,注册时间2020-01-01 10:00:00 试卷信息表examination_info(exam_id试卷ID, tag试卷类别, difficulty试卷难度, duration考试时长, release_time发布时间) 示例数据如下: +----+---------+--------+------------+----------+---------------------+ | id | exam_id | tag | difficulty | duration | release_time | +----+---------+--------+------------+----------+---------------------+ | 1 | 9001 | SQL | hard | 60 | 2021-09-01 06:00:00 | | 2 | 9002 | C++ | easy | 60 | 2020-02-01 10:00:00 | | 3 | 9003 | 算法 | medium | 80 | 2020-08-02 10:00:00 | +----+---------+--------+------------+----------+---------------------+ 试卷作答记录表exam_record(uid用户ID, exam_id试卷ID, start_time开始作答时间, submit_time交卷时间, score得分) 示例数据如下: +----+------+---------+---------------------+---------------------+-------+ | id | uid | exam_id | start_time | submit_time | score | +----+------+---------+---------------------+---------------------+-------+ | 1 | 1001 | 9001 | 2021-09-01 09:01:01 | 2021-09-01 09:41:01 | 70 | | 2 | 1002 | 9003 | 2021-09-01 12:01:01 | 2021-09-01 12:21:01 | 60 | | 3 | 1002 | 9002 | 2021-09-02 12:01:01 | 2021-09-02 12:31:01 | 70 | | 4 | 1002 | 9001 | 2021-09-01 19:01:01 | 2021-09-01 19:40:01 | 80 | | 5 | 1002 | 9003 | 2021-08-01 12:01:01 | 2021-08-01 12:21:01 | 60 | | 6 | 1002 | 9002 | 2021-08-02 12:01:01 | 2021-08-02 12:31:01 | 70 | | 7 | 1002 | 9001 | 2021-09-01 19:01:01 | 2021-09-01 19:40:01 | 85 | | 8 | 1002 | 9002 | 2021-07-06 12:01:01 | NULL | NULL | | 9 | 1003 | 9003 | 2021-09-07 10:01:01 | 2021-09-07 10:31:01 | 86 | | 10 | 1003 | 9003 | 2021-09-08 12:01:01 | 2021-09-08 12:11:01 | 40 | | 11 | 1003 | 9001 | 2021-09-01 13:01:01 | 2021-09-01 13:41:01 | 70 | | 12 | 1003 | 9002 | 2021-09-08 14:01:01 | NULL | NULL | | 13 | 1003 | 9003 | 2021-09-08 15:01:01 | NULL | NULL | | 14 | 1005 | 9001 | 2021-09-01 12:01:01 | 2021-09-01 12:31:01 | 90 | | 15 | 1005 | 9002 | 2021-09-01 12:01:01 | 2021-09-01 12:31:01 | 88 | | 16 | 1005 | 9002 | 2021-09-02 12:11:01 | 2021-09-02 12:31:01 | 89 | +----+------+---------+---------------------+---------------------+-------+ 统计作答SQL类别的试卷得分大于过80的人的用户等级分布,按数量降序排序(保证数量都不同)。 示例数据结果输出如下: 解释:9001为SQL类试卷,作答该试卷大于80分的人有1002、1003、1005共3人,6级两人,5级一人。 🚀 建表语句 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 user_info; 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; 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 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, '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:41:01', 79), (1002, 9003, '2021-09-01 12:01:01', '2021-09-01 12:21:01', 60), (1002, 9002, '2021-09-01 12:01:01', '2021-09-01 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-09-01 12:01:01', '2021-09-01 12:31:01', 70), (1002, 9001, '2021-09-01 19:01:01', '2021-09-01 19:40:01', 85), (1002, 9002, '2021-09-01 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', 81), (1003, 9002, '2021-09-01 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), (1006, 9002, '2021-09-01 12:11:01', '2021-09-01 12:31:01', 89); 🍌🍌 答案 SELECT level, COUNT(DISTINCT uid) AS level_cnt FROM exam_record er JOIN user_info ui USING(uid) JOIN examination_info ei USING(exam_id) WHERE ei.tag='SQL' AND er.score > 80 GROUP BY level ORDER BY COUNT(DISTINCT uid) DESC, level DESC;

4.2 🌈 合并查询 🚀 SQL23 每个题目和每份试卷被作答的人数和次数

📖 exam_record表结构 📖 practice_record表结构

🚀 题目描述 现有试卷作答记录表exam_record(uid用户ID, exam_id试卷ID, start_time开始作答时间, submit_time交卷时间, score得分): +----+------+---------+---------------------+---------------------+-------+ | id | uid | exam_id | start_time | submit_time | score | +----+------+---------+---------------------+---------------------+-------+ | 1 | 1001 | 9001 | 2021-09-01 09:01:01 | 2021-09-01 09:41:01 | 81 | | 2 | 1002 | 9002 | 2021-09-01 12:01:01 | 2021-09-01 12:31:01 | 70 | | 3 | 1002 | 9001 | 2021-09-01 19:01:01 | 2021-09-01 19:40:01 | 80 | | 4 | 1002 | 9002 | 2021-09-01 12:01:01 | 2021-09-01 12:31:01 | 70 | | 5 | 1004 | 9001 | 2021-09-01 19:01:01 | 2021-09-01 19:40:01 | 85 | | 6 | 1002 | 9002 | 2021-09-01 12:01:01 | NULL | NULL | +----+------+---------+---------------------+---------------------+-------+ 题目练习表practice_record(uid用户ID, question_id题目ID, submit_time提交时间, score得分): +----+------+-------------+---------------------+-------+ | id | uid | question_id | submit_time | score | +----+------+-------------+---------------------+-------+ | 1 | 1001 | 8001 | 2021-08-02 11:41:01 | 60 | | 2 | 1002 | 8001 | 2021-09-02 19:30:01 | 50 | | 3 | 1002 | 8001 | 2021-09-02 19:20:01 | 70 | | 4 | 1002 | 8002 | 2021-09-02 19:38:01 | 70 | | 5 | 1003 | 8001 | 2021-08-02 19:38:01 | 70 | | 6 | 1003 | 8001 | 2021-08-02 19:48:01 | 90 | | 7 | 1003 | 8002 | 2021-08-01 19:38:01 | 80 | +----+------+-------------+---------------------+-------+ 请统计每个题目和每份试卷被作答的人数和次数,分别按照"试卷"和"题目"的uv & pv降序显示,示例数据结果输出如下: +------+----+----+ | tid | uv | pv | +------+----+----+ | 9001 | 3 | 3 | | 9002 | 1 | 3 | | 8001 | 3 | 5 | | 8002 | 2 | 2 | +------+----+----+ 解释:“试卷”有3人共练习3次试卷9001,1人作答3次9002;“刷题”有3人刷5次8001,有2人刷2次8002 🚀 建表语句 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; 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 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, 8001, '2021-08-02 19:38:01', 70), (1003, 8001, '2021-08-02 19:48:01', 90), (1003, 8002, '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:41:01', 81), (1002, 9002, '2021-09-01 12:01:01', '2021-09-01 12:31:01', 70), (1002, 9001, '2021-09-01 19:01:01', '2021-09-01 19:40:01', 80), (1002, 9002, '2021-09-01 12:01:01', '2021-09-01 12:31:01', 70), (1004, 9001, '2021-09-01 19:01:01', '2021-09-01 19:40:01', 85), (1002, 9002, '2021-09-01 12:01:01', null, null); 🍌🍌 答案 SELECT exam_id as tid, count(distinct uid) as uv, count(uid) as pv from exam_record group by exam_id union ALL SELECT question_id as tid, count(distinct uid) as uv, count(uid) as pv from practice_record group by question_id order by LEFT(tid,1) DESC,uv DESC,pv DESC;

🚀 SQL24 分别满足两个活动的人

📖 examination_info表结构 📖 exam_record表结构

🚀 题目描述 为了促进更多用户在牛客平台学习和刷题进步,我们会经常给一些既活跃又表现不错的用户发放福利。 假使以前我们有两拨运营活动,分别给每次试卷得分都能到85分的人(activity1)、 至少有一次用了一半时间就完成高难度试卷且分数大于80的人(activity2)发了福利券。 现在,需要你一次性将这两个活动满足的人筛选出来,交给运营同学。 请写出一个SQL实现:输出2021年里,所有每次试卷得分都能到85分的人以及至少有一次用了一半时间就完成高难度试卷且分数大于80的人的id和活动号, 按用户ID排序输出。 现有试卷信息表examination_info(exam_id试卷ID, tag试卷类别, difficulty试卷难度, duration考试时长, release_time发布时间): +----+---------+--------+------------+----------+---------------------+ | id | exam_id | tag | difficulty | duration | release_time | +----+---------+--------+------------+----------+---------------------+ | 1 | 9001 | SQL | hard | 60 | 2021-09-01 06:00:00 | | 2 | 9002 | C++ | hard | 60 | 2021-09-01 06:00:00 | | 3 | 9003 | 算法 | medium | 80 | 2021-09-01 10:00:00 | +----+---------+--------+------------+----------+---------------------+ 试卷作答记录表exam_record(uid用户ID, exam_id试卷ID, start_time开始作答时间, submit_time交卷时间, score得分): +----+------+---------+---------------------+---------------------+-------+ | id | uid | exam_id | start_time | submit_time | score | +----+------+---------+---------------------+---------------------+-------+ | 1 | 1001 | 9001 | 2021-09-01 09:01:01 | 2021-09-01 09:31:00 | 81 | | 2 | 1002 | 9002 | 2021-09-01 12:01:01 | 2021-09-01 12:31:01 | 70 | | 3 | 1003 | 9001 | 2021-09-01 19:01:01 | 2021-09-01 19:40:01 | 86 | | 4 | 1003 | 9002 | 2021-09-01 12:01:01 | 2021-09-01 12:31:51 | 89 | | 5 | 1004 | 9001 | 2021-09-01 19:01:01 | 2021-09-01 19:30:01 | 85 | +----+------+---------+---------------------+---------------------+-------+ 示例数据输出结果: +------+-----------+ | uid | activity | +------+-----------+ | 1001 | activity2 | | 1003 | activity1 | | 1004 | activity1 | | 1004 | activity2 | +------+-----------+ 解释:用户1001最小分数81不满足活动1,但29分59秒完成了60分钟长的试卷得分81,满足活动2; 1003最小分数86满足活动1,完成时长都大于试卷时长的一半,不满足活动2; 用户1004刚好用了一半时间(30分钟整)完成了试卷得分85,满足活动1和活动2。 🚀 建表语句 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); 🍌🍌 答案 (select r.uid, 'activity1' as activity from exam_record r where year(submit_time) = 2021 group by r.uid having min(score) >= 85) union all (select r.uid,'activity2' as activity from exam_record r left join examination_info i on r.exam_id = i.exam_id where year(submit_time) = 2021 and i.difficulty = 'hard' and score >=80 and timestampdiff(second,r.start_time,r.submit_time)<= i.duration*30 group by r.uid) order by uid;

4.3 🌈 连接查询 🚀 SQL25 满足条件的用户的试卷完成数和题目练习数

📖 user_info表结构 📖 examination_info表结构 📖 exam_record表结构 📖 practice_record表结构

🚀 题目描述 现有用户信息表user_info(uid用户ID,nick_name昵称, achievement成就值, level等级, job职业方向, register_time注册时间): +----+------+------------+-------------+-------+--------+---------------------+ | id | uid | nick_name | achievement | level | job | register_time | +----+------+------------+-------------+-------+--------+---------------------+ | 1 | 1001 | 牛客1号 | 3100 | 7 | 算法 | 2020-01-01 10:00:00 | | 2 | 1002 | 牛客2号 | 2300 | 7 | 算法 | 2020-01-01 10:00:00 | | 3 | 1003 | 牛客3号 | 2500 | 7 | 算法 | 2020-01-01 10:00:00 | | 4 | 1004 | 牛客4号 | 1200 | 5 | 算法 | 2020-01-01 10:00:00 | | 5 | 1005 | 牛客5号 | 1600 | 6 | C++ | 2020-01-01 10:00:00 | | 6 | 1006 | 牛客6号 | 2000 | 6 | C++ | 2020-01-01 10:00:00 | +----+------+------------+-------------+-------+--------+---------------------+ 试卷信息表examination_info(exam_id试卷ID, tag试卷类别, difficulty试卷难度, duration考试时长, release_time发布时间): +----+---------+--------+------------+----------+---------------------+ | id | exam_id | tag | difficulty | duration | release_time | +----+---------+--------+------------+----------+---------------------+ | 1 | 9001 | SQL | hard | 60 | 2021-09-01 06:00:00 | | 2 | 9002 | C++ | hard | 60 | 2021-09-01 06:00:00 | | 3 | 9003 | 算法 | medium | 80 | 2021-09-01 10:00:00 | +----+---------+--------+------------+----------+---------------------+ 试卷作答记录表exam_record(uid用户ID, exam_id试卷ID, start_time开始作答时间, submit_time交卷时间, score得分): +----+------+---------+---------------------+---------------------+-------+ | id | uid | exam_id | start_time | submit_time | score | +----+------+---------+---------------------+---------------------+-------+ | 1 | 1001 | 9001 | 2021-09-01 09:01:01 | 2021-09-01 09:31:00 | 81 | | 2 | 1002 | 9002 | 2021-09-01 12:01:01 | 2021-09-01 12:31:01 | 81 | | 3 | 1003 | 9001 | 2021-09-01 19:01:01 | 2021-09-01 19:40:01 | 86 | | 4 | 1003 | 9002 | 2021-09-01 12:01:01 | 2021-09-01 12:31:51 | 89 | | 5 | 1004 | 9001 | 2021-09-01 19:01:01 | 2021-09-01 19:30:01 | 85 | | 6 | 1005 | 9002 | 2021-09-01 12:01:01 | 2021-09-01 12:31:02 | 85 | | 7 | 1006 | 9003 | 2021-09-07 10:01:01 | 2021-09-07 10:21:01 | 84 | | 8 | 1006 | 9001 | 2021-09-07 10:01:01 | 2021-09-07 10:21:01 | 80 | +----+------+---------+---------------------+---------------------+-------+ 题目练习记录表practice_record(uid用户ID, question_id题目ID, submit_time提交时间, score得分): +----+------+-------------+---------------------+-------+ | id | uid | question_id | submit_time | score | +----+------+-------------+---------------------+-------+ | 1 | 1001 | 8001 | 2021-08-02 11:41:01 | 60 | | 2 | 1002 | 8001 | 2021-09-02 19:30:01 | 50 | | 3 | 1002 | 8001 | 2021-09-02 19:20:01 | 70 | | 4 | 1002 | 8002 | 2021-09-02 19:38:01 | 70 | | 5 | 1004 | 8001 | 2021-08-02 19:38:01 | 70 | | 6 | 1004 | 8002 | 2021-08-02 19:48:01 | 90 | | 7 | 1001 | 8002 | 2021-08-02 19:38:01 | 70 | | 8 | 1004 | 8002 | 2021-08-02 19:48:01 | 90 | | 9 | 1004 | 8002 | 2021-08-02 19:58:01 | 94 | | 10 | 1004 | 8003 | 2021-08-02 19:38:01 | 70 | | 11 | 1004 | 8003 | 2021-08-02 19:48:01 | 90 | | 12 | 1004 | 8003 | 2021-08-01 19:38:01 | 80 | +----+------+-------------+---------------------+-------+ 请你找到高难度SQL试卷得分平均值大于80并且是7级的红名大佬,统计他们的2021年试卷总完成次数和题目总练习次数,只保留2021年有试卷完成记录的用户。 结果按试卷完成数升序,按题目练习数降序。 示例数据输出如下: +------+----------+--------------+ | uid | exam_cnt | question_cnt | +------+----------+--------------+ | 1001 | 1 | 2 | | 1003 | 2 | 0 | +------+----------+--------------+ 解释:用户1001、1003、1004、1006满足高难度SQL试卷得分平均值大于80,但只有1001、1003是7级红名大佬; 1001完成了1次试卷1001,练习了2次题目; 1003完成了2次试卷9001、9002,未练习题目(因此计数为0) 🚀 建表语句 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); 🍌🍌 答案 select er1.uid as uid, count(distinct er1.exam_id) as exam_cnt, count(distinct pr1.id) as question_cnt from exam_record er1 left join practice_record pr1 on er1.uid = pr1.uid and year(er1.submit_time)=2021 and YEAR(pr1.submit_time)=2021 where er1.uid in ( select er.uid from user_info ui left join exam_record er on ui.uid = er.uid join examination_info ei on er.exam_id = ei.exam_id where ei.tag = 'SQL' and ui.level = 7 and difficulty = 'hard' and year(submit_time)=2021 group by ui.uid having avg(er.score) >80) group by er1.uid order by exam_cnt , question_cnt desc;

🚀 SQL26 每个6/7级用户活跃情况

📖 user_info表结构 📖 examination_info表结构 📖 exam_record表结构 📖 practice_record表结构

🚀 题目描述 现有用户信息表user_info(uid用户ID,nick_name昵称, achievement成就值, level等级, job职业方向, register_time注册时间): +----+------+------------+-------------+-------+--------+---------------------+ | id | uid | nick_name | achievement | level | job | register_time | +----+------+------------+-------------+-------+--------+---------------------+ | 1 | 1001 | 牛客1号 | 3100 | 7 | 算法 | 2020-01-01 10:00:00 | | 2 | 1002 | 牛客2号 | 2300 | 7 | 算法 | 2020-01-01 10:00:00 | | 3 | 1003 | 牛客3号 | 2500 | 7 | 算法 | 2020-01-01 10:00:00 | | 4 | 1004 | 牛客4号 | 1200 | 5 | 算法 | 2020-01-01 10:00:00 | | 5 | 1005 | 牛客5号 | 1600 | 6 | C++ | 2020-01-01 10:00:00 | | 6 | 1006 | 牛客6号 | 2000 | 6 | C++ | 2020-01-01 10:00:00 | +----+------+------------+-------------+-------+--------+---------------------+ 试卷信息表examination_info(exam_id试卷ID, tag试卷类别, difficulty试卷难度, duration考试时长, release_time发布时间): +----+---------+--------+------------+----------+---------------------+ | id | exam_id | tag | difficulty | duration | release_time | +----+---------+--------+------------+----------+---------------------+ | 1 | 9001 | SQL | hard | 60 | 2021-09-01 06:00:00 | | 2 | 9002 | C++ | hard | 60 | 2021-09-01 06:00:00 | | 3 | 9003 | 算法 | medium | 80 | 2021-09-01 10:00:00 | +----+---------+--------+------------+----------+---------------------+ 试卷作答记录表exam_record(uid用户ID, exam_id试卷ID, start_time开始作答时间, submit_time交卷时间, score得分): +----+------+---------+---------------------+---------------------+-------+ | id | uid | exam_id | start_time | submit_time | score | +----+------+---------+---------------------+---------------------+-------+ | 1 | 1001 | 9001 | 2021-09-01 09:01:01 | 2021-09-01 09:31:00 | 81 | | 2 | 1002 | 9002 | 2021-09-01 12:01:01 | 2021-09-01 12:31:01 | 81 | | 3 | 1003 | 9001 | 2021-09-01 19:01:01 | 2021-09-01 19:40:01 | 86 | | 4 | 1003 | 9002 | 2021-09-01 12:01:01 | 2021-09-01 12:31:51 | 89 | | 5 | 1004 | 9001 | 2021-09-01 19:01:01 | 2021-09-01 19:30:01 | 85 | | 6 | 1005 | 9002 | 2021-09-01 12:01:01 | 2021-09-01 12:31:02 | 85 | | 7 | 1006 | 9003 | 2021-09-07 10:01:01 | 2021-09-07 10:21:01 | 84 | | 8 | 1006 | 9001 | 2021-09-07 10:01:01 | 2021-09-07 10:21:01 | 80 | +----+------+---------+---------------------+---------------------+-------+ 题目练习记录表practice_record(uid用户ID, question_id题目ID, submit_time提交时间, score得分): +----+------+-------------+---------------------+-------+ | id | uid | question_id | submit_time | score | +----+------+-------------+---------------------+-------+ | 1 | 1001 | 8001 | 2021-08-02 11:41:01 | 60 | | 2 | 1002 | 8001 | 2021-09-02 19:30:01 | 50 | | 3 | 1002 | 8001 | 2021-09-02 19:20:01 | 70 | | 4 | 1002 | 8002 | 2021-09-02 19:38:01 | 70 | | 5 | 1004 | 8001 | 2021-08-02 19:38:01 | 70 | | 6 | 1004 | 8002 | 2021-08-02 19:48:01 | 90 | | 7 | 1001 | 8002 | 2021-08-02 19:38:01 | 70 | | 8 | 1004 | 8002 | 2021-08-02 19:48:01 | 90 | | 9 | 1004 | 8002 | 2021-08-02 19:58:01 | 94 | | 10 | 1004 | 8003 | 2021-08-02 19:38:01 | 70 | | 11 | 1004 | 8003 | 2021-08-02 19:48:01 | 90 | | 12 | 1004 | 8003 | 2021-08-01 19:38:01 | 80 | +----+------+-------------+---------------------+-------+ 请统计每个6/7级用户总活跃月份数、2021年活跃天数、2021年试卷作答活跃天数、 2021年答题活跃天数,按照总活跃月份数、2021年活跃天数降序排序。由示例数据结果输出如下: +------+-----------------+---------------+--------------------+------------------------+ | uid | act_month_total | act_days_2021 | act_days_2021_exam | act_days_2021_question | +------+-----------------+---------------+--------------------+------------------------+ | 1001 | 2 | 2 | 1 | 1 | | 1002 | 1 | 2 | 1 | 1 | | 1003 | 1 | 1 | 1 | 0 | | 1005 | 1 | 1 | 1 | 0 | | 1006 | 1 | 1 | 1 | 0 | +------+-----------------+---------------+--------------------+------------------------+ 解释:6/7级用户共有5个,其中1006在202109、202108、202008共3个月活跃过, 2021年活跃的日期有20210907、20210804、20210803、20210802共4天,2021年在试卷作答区20210907活跃1天,在题目练习区活跃了3天。 🚀 建表语句 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 t1.uid, count(distinct act_month) act_month_total, count(distinct case when year(act_day)=2021 then act_day end) act_days_2021, count(distinct case when left(tag,1)=9 and year(act_day)=2021 then act_day end) act_days_2021_exam, count(distinct case when left(tag,1)=8 and year(act_day)=2021 then act_day end) act_days_2021_question from user_info t1 left join (select uid , date_format(start_time,'%Y%m') act_month, date_format(start_time,'%Y%m%d') act_day, exam_id tag from exam_record union all select uid, date_format(submit_time,'%Y%m') act_month, date_format(submit_time,'%Y%m%d') act_day, question_id tag from practice_record) t2 on t1.uid=t2.uid where t1.uid in (select uid from user_info where level in (6,7)) group by uid order by act_month_total desc,act_days_2021 desc;

🐴 5.窗口函数

5.1 🌈 专用窗口函数 🚀 SQL27 每类试卷得分前3名

📖 examination_info 表结构 📖 exam_record表结构

🚀 题目描述 现有试卷信息表examination_info(exam_id试卷ID, tag试卷类别, difficulty试卷难度, duration考试时长, release_time发布时间): +----+---------+--------+------------+----------+---------------------+ | id | exam_id | tag | difficulty | duration | release_time | +----+---------+--------+------------+----------+---------------------+ | 1 | 9001 | SQL | hard | 60 | 2021-09-01 06:00:00 | | 2 | 9002 | SQL | hard | 60 | 2021-09-01 06:00:00 | | 3 | 9003 | 算法 | medium | 80 | 2021-09-01 10:00:00 | +----+---------+--------+------------+----------+---------------------+ 试卷作答记录表exam_record(uid用户ID, exam_id试卷ID, start_time开始作答时间, submit_time交卷时间, score得分): +----+------+---------+---------------------+---------------------+-------+ | id | uid | exam_id | start_time | submit_time | score | +----+------+---------+---------------------+---------------------+-------+ | 1 | 1001 | 9001 | 2021-09-01 09:01:01 | 2021-09-01 09:31:00 | 78 | | 2 | 1001 | 9001 | 2021-09-01 09:01:01 | 2021-09-01 09:31:00 | 81 | | 3 | 1002 | 9002 | 2021-09-01 12:01:01 | 2021-09-01 12:31:01 | 81 | | 4 | 1003 | 9001 | 2021-09-01 19:01:01 | 2021-09-01 19:40:01 | 86 | | 5 | 1003 | 9002 | 2021-09-01 12:01:01 | 2021-09-01 12:31:51 | 89 | | 6 | 1004 | 9001 | 2021-09-01 19:01:01 | 2021-09-01 19:30:01 | 85 | | 7 | 1005 | 9003 | 2021-09-01 12:01:01 | 2021-09-01 12:31:02 | 85 | | 8 | 1006 | 9003 | 2021-09-07 10:01:01 | 2021-09-07 10:21:01 | 84 | | 9 | 1003 | 9003 | 2021-09-08 12:01:01 | 2021-09-08 12:11:01 | 40 | | 10 | 1003 | 9002 | 2021-09-01 14:01:01 | NULL | NULL | +----+------+---------+---------------------+---------------------+-------+ 找到每类试卷得分的前3名,如果两人最大分数相同,选择最小分数大者,如果还相同,选择uid大者。由示例数据结果输出如下: +--------+------+----+ | tag | uid | rk | +--------+------+----+ | SQL | 1003 | 1 | | SQL | 1004 | 2 | | SQL | 1002 | 3 | | 算法 | 1005 | 1 | | 算法 | 1006 | 2 | | 算法 | 1003 | 3 | +--------+------+----+ 解释:有作答得分记录的试卷tag有SQL和算法,SQL试卷用户1001、1002、1003、1004有作答得分, 最高得分分别为81、81、89、85,最低得分分别为78、81、86、40, 因此先按最高得分排名再按最低得分排名取前三为1003、1004、1002。 🚀 建表语句 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 tag,uid,rk from ( select tag, uid, rank() over ( partition by tag order by tag,max(score) desc,min(score) desc,uid desc) as rk from exam_record er left join examination_info ei on er.exam_id = ei.exam_id group by tag,uid ) as t where rk<=3;

🚀 SQL28 第二快/慢用时之差大于试卷时长一半的试卷

📖 examination_info 表结构 📖 exam_record 表结构

🚀 题目描述 现有试卷信息表examination_info(exam_id试卷ID, tag试卷类别, difficulty试卷难度, duration考试时长, release_time发布时间): +----+---------+--------+------------+----------+---------------------+ | id | exam_id | tag | difficulty | duration | release_time | +----+---------+--------+------------+----------+---------------------+ | 1 | 9001 | SQL | hard | 60 | 2021-09-01 06:00:00 | | 2 | 9002 | C++ | hard | 60 | 2021-09-01 06:00:00 | | 3 | 9003 | 算法 | medium | 80 | 2021-09-01 10:00:00 | +----+---------+--------+------------+----------+---------------------+ 试卷作答记录表exam_record(uid用户ID, exam_id试卷ID, start_time开始作答时间, submit_time交卷时间, score得分): +----+------+---------+---------------------+---------------------+-------+ | id | uid | exam_id | start_time | submit_time | score | +----+------+---------+---------------------+---------------------+-------+ | 1 | 1001 | 9001 | 2021-09-01 09:01:01 | 2021-09-01 09:51:01 | 78 | | 2 | 1001 | 9002 | 2021-09-01 09:01:01 | 2021-09-01 09:31:00 | 81 | | 3 | 1002 | 9002 | 2021-09-01 12:01:01 | 2021-09-01 12:31:01 | 81 | | 4 | 1003 | 9001 | 2021-09-01 19:01:01 | 2021-09-01 19:59:01 | 86 | | 5 | 1003 | 9002 | 2021-09-01 12:01:01 | 2021-09-01 12:31:51 | 89 | | 6 | 1004 | 9002 | 2021-09-01 19:01:01 | 2021-09-01 19:30:01 | 85 | | 7 | 1005 | 9001 | 2021-09-01 12:01:01 | 2021-09-01 12:31:02 | 85 | | 8 | 1006 | 9001 | 2021-09-07 10:01:01 | 2021-09-07 10:12:01 | 84 | | 9 | 1003 | 9001 | 2021-09-08 12:01:01 | 2021-09-08 12:11:01 | 40 | | 10 | 1003 | 9002 | 2021-09-01 14:01:01 | NULL | NULL | | 11 | 1005 | 9001 | 2021-09-01 14:01:01 | NULL | NULL | | 12 | 1003 | 9003 | 2021-09-08 15:01:01 | NULL | NULL | +----+------+---------+---------------------+---------------------+-------+ 找到第二快和第二慢用时之差大于试卷时长的一半的试卷信息,按试卷ID降序排序。由示例数据结果输出如下: 解释:试卷9001被作答用时有50分钟、50分钟、30分1秒、11分钟、10分钟, 第二快和第二慢用时之差为50分钟-11分钟=39分钟,试卷时长为60分钟, 因此满足大于试卷时长一半的条件,输出试卷ID、时长、发布时间。 🚀 建表语句 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); 🍌🍌 答案 SELECT distinct exam_id, duration, release_time FROM (SELECT exam_id, duration, release_time, sum(case when rank1= 2 then costtime when rank2= 2 then -costtime else 0 end ) as sub from( SELECT exam_id,duration, release_time, TIMESTAMPDIFF(minute,start_time, submit_time) as costtime, row_number() over (partition by exam_id order by TIMESTAMPDIFF(minute,start_time, submit_time) desc) as rank1, row_number() over (partition by exam_id order by TIMESTAMPDIFF(minute,start_time, submit_time) asc) as rank2 FROM exam_record JOIN examination_info USING (exam_id) where submit_time is not null ) a group by exam_id ) b where sub * 2 >= duration order by exam_id desc;

🚀SQL29 连续两次作答试卷的最大时间窗

📖 exam_record 表结构

🚀 题目描述 现有试卷作答记录表exam_record(uid用户ID, exam_id试卷ID, start_time开始作答时间, submit_time交卷时间, score得分): +----+------+---------+---------------------+---------------------+-------+ | id | uid | exam_id | start_time | submit_time | score | +----+------+---------+---------------------+---------------------+-------+ | 1 | 1006 | 9003 | 2021-09-07 10:01:01 | 2021-09-07 10:21:02 | 84 | | 2 | 1006 | 9001 | 2021-09-01 12:11:01 | 2021-09-01 12:31:01 | 89 | | 3 | 1006 | 9002 | 2021-09-06 10:01:01 | 2021-09-06 10:21:01 | 81 | | 4 | 1005 | 9002 | 2021-09-05 10:01:01 | 2021-09-05 10:21:01 | 81 | | 5 | 1005 | 9001 | 2021-09-05 10:31:01 | 2021-09-05 10:51:01 | 81 | +----+------+---------+---------------------+---------------------+-------+ 请计算在2021年至少有两天作答过试卷的人中,计算该年连续两次作答试卷的最大时间窗days_window, 那么根据该年的历史规律他在days_window天里平均会做多少套试卷,按最大时间窗和平均做答试卷套数倒序排序。 由示例数据结果输出如下: +------+-------------+--------------+ | uid | days_window | avg_exam_cnt | +------+-------------+--------------+ | 1006 | 6 | 2.57 | +------+-------------+--------------+ 解释:用户1006分别在20210901、20210906、20210907作答过3次试卷,连续两次作答最大时间窗为6天(1号到6号), 他1号到7号这7天里共做了3张试卷,平均每天3/7=0.428571张,那么6天里平均会做0.428571*6=2.57张试卷(保留两位小数); 用户1005在20210905做了两张试卷,但是只有一天的作答记录,过滤掉。 🚀 建表语句 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); 🍌🍌 答案 SELECT uid,max(day1)+1 days_window, round((count(*)/(sum(day1)+1))*(max(day1)+1),2) avg_exam_cnt from( select uid,date1,lag1,datediff(date1,lag1) day1 from( select uid,date(start_time) date1, lag(date(start_time),1,date(start_time)) over(partition by uid order by start_time) lag1 from exam_record where uid in( select uid from exam_record where year(start_time)=2021 group by uid having count(distinct date(start_time))>1) and year(start_time)=2021) a) b group by uid order by days_window desc,avg_exam_cnt desc; 备注: 按最大时间窗和平均做答试卷套数倒序排序,保留两位小数

🚀 SQL30 近三个月未完成试卷数为0的用户完成情况

📖 exam_record 表结构

🚀 题目描述 现有试卷作答记录表exam_record(uid:用户ID, exam_id:试卷ID, start_time:开始作答时间, submit_time:交卷时间,为空的话则代表未完成, score:得分): +----+------+---------+---------------------+---------------------+-------+ | id | uid | exam_id | start_time | submit_time | score | +----+------+---------+---------------------+---------------------+-------+ | 1 | 1006 | 9003 | 2021-09-06 10:01:01 | 2021-09-06 10:21:02 | 84 | | 2 | 1006 | 9001 | 2021-08-02 12:11:01 | 2021-08-02 12:31:01 | 89 | | 3 | 1006 | 9002 | 2021-06-06 10:01:01 | 2021-06-06 10:21:01 | 81 | | 4 | 1006 | 9002 | 2021-05-06 10:01:01 | 2021-05-06 10:21:01 | 81 | | 5 | 1006 | 9001 | 2021-05-01 12:01:01 | NULL | NULL | | 6 | 1001 | 9001 | 2021-09-05 10:31:01 | 2021-09-05 10:51:01 | 81 | | 7 | 1001 | 9003 | 2021-08-01 09:01:01 | 2021-08-01 09:51:11 | 78 | | 8 | 1001 | 9002 | 2021-07-01 09:01:01 | 2021-07-01 09:31:00 | 81 | | 9 | 1001 | 9002 | 2021-07-01 12:01:01 | 2021-07-01 12:31:01 | 81 | | 10 | 1001 | 9002 | 2021-07-01 12:01:01 | NULL | NULL | +----+------+---------+---------------------+---------------------+-------+ 找到每个人近三个有试卷作答记录的月份中没有试卷是未完成状态的用户的试卷作答完成数,按试卷完成数和用户ID降序排名。 由示例数据结果输出如下: +------+-------------------+ | uid | exam_complete_cnt | +------+-------------------+ | 1006 | 3 | +------+-------------------+ 解释:用户1006近三个有作答试卷的月份为202109、202108、202106,作答试卷数为3,全部完成; 用户1001近三个有作答试卷的月份为202109、202108、202107,作答试卷数为5,完成试卷数为4, 因为有未完成试卷,故过滤掉。 🚀 建表语句 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-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-05-06 10:01:01', '2021-05-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); select a.uid, count(a.start_time) as exam_complete_cnt FROM ( select uid, start_time, submit_time, DENSE_RANK() over(partition by uid order by date_format(start_time, '%Y%m') desc) as time_rank from exam_record ) as a where a.time_rank <= 3 group by a.uid having count(a.start_time) = count(a.submit_time) order by exam_complete_cnt desc, uid desc;

🚀 SQL31 未完成率较高的50%用户近三个月答卷情况

📖 user_info 表结构 📖 examination_info 表结构 📖 exam_record 表结构

🚀 题目描述 现有用户信息表user_info(uid用户ID,nick_name昵称, achievement成就值, level等级, job职业方向, register_time注册时间): +----+------+---------------+-------------+-------+--------+---------------------+ | id | uid | nick_name | achievement | level | job | register_time | +----+------+---------------+-------------+-------+--------+---------------------+ | 1 | 1001 | 牛客1 | 3200 | 7 | 算法 | 2020-01-01 10:00:00 | | 2 | 1002 | 牛客2号 | 2500 | 6 | 算法 | 2020-01-01 10:00:00 | | 3 | 1003 | 牛客3号♂ | 2200 | 5 | 算法 | 2020-01-01 10:00:00 | +----+------+---------------+-------------+-------+--------+---------------------+ 试卷信息表examination_info(exam_id试卷ID, tag试卷类别, difficulty试卷难度, duration考试时长, release_time发布时间): +----+---------+--------+------------+----------+---------------------+ | id | exam_id | tag | difficulty | duration | release_time | +----+---------+--------+------------+----------+---------------------+ | 1 | 9001 | SQL | hard | 60 | 2020-01-01 10:00:00 | | 2 | 9002 | SQL | hard | 80 | 2020-01-01 10:00:00 | | 3 | 9003 | 算法 | hard | 80 | 2020-01-01 10:00:00 | | 4 | 9004 | PYTHON | medium | 70 | 2020-01-01 10:00:00 | +----+---------+--------+------------+----------+---------------------+ 试卷作答记录表exam_record(uid用户ID, exam_id试卷ID, start_time开始作答时间, submit_time交卷时间, score得分): +----+------+---------+---------------------+---------------------+-------+ | id | uid | exam_id | start_time | submit_time | score | +----+------+---------+---------------------+---------------------+-------+ | 1 | 1001 | 9001 | 2020-01-01 09:01:01 | 2020-01-01 09:21:59 | 90 | | 2 | 1002 | 9001 | 2020-01-20 10:01:01 | NULL | NULL | | 3 | 1002 | 9001 | 2020-02-01 12:11:01 | NULL | NULL | | 4 | 1003 | 9001 | 2020-03-01 19:01:01 | NULL | NULL | | 5 | 1001 | 9001 | 2020-03-01 12:01:01 | NULL | NULL | | 6 | 1002 | 9001 | 2020-03-01 12:01:01 | 2020-03-01 12:41:01 | 90 | | 7 | 1002 | 9001 | 2020-05-02 19:01:01 | 2020-05-02 19:32:00 | 90 | | 8 | 1001 | 9002 | 2020-01-02 19:01:01 | 2020-01-02 19:59:01 | 69 | | 9 | 1001 | 9002 | 2020-02-02 12:01:01 | 2020-02-02 12:20:01 | 99 | | 10 | 1002 | 9002 | 2020-02-02 12:01:01 | NULL | NULL | | 11 | 1002 | 9002 | 2020-02-02 12:01:01 | 2020-02-02 12:43:01 | 81 | | 12 | 1002 | 9002 | 2020-03-02 12:11:01 | NULL | NULL | | 13 | 1001 | 9001 | 2020-01-02 10:01:01 | 2020-01-02 10:31:01 | 89 | | 14 | 1001 | 9002 | 2020-01-01 12:11:01 | NULL | NULL | | 15 | 1002 | 9001 | 2020-01-01 18:01:01 | 2020-01-01 18:59:02 | 90 | | 16 | 1002 | 9003 | 2020-05-06 12:01:01 | NULL | NULL | | 17 | 1001 | 9002 | 2020-05-05 18:01:01 | NULL | NULL | +----+------+---------+---------------------+---------------------+-------+ 请统计SQL试卷上未完成率较高的50%用户中,6级和7级用户在有试卷作答记录的近三个月中,每个月的答卷数目和完成数目。按用户ID、月份升序排序。 由示例数据结果输出如下: +------+-------------+-----------+--------------+ | uid | start_month | total_cnt | complete_cnt | +------+-------------+-----------+--------------+ | 1002 | 202002 | 3 | 1 | | 1002 | 202003 | 2 | 1 | | 1002 | 202005 | 2 | 1 | +------+-------------+-----------+--------------+ 解释: 1001、1002、1003分别排在1.0、0.5、0.0的位置,因此较高的50%用户(排位<=0.5)为1002、1003; 1003不是6级或7级; 有试卷作答记录的近三个月为202005、202003、202002; 这三个月里1002的作答题数分别为3、2、2,完成数目分别为1、1、1。 🚀 建表语句 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', 3200, 7, '算法', '2020-01-01 10:00:00'), (1002, '牛客2号', 2500, 6, '算法', '2020-01-01 10:00:00'), (1003, '牛客3号♂', 2200, 5, '算法', '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', '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-01-01 09:01:01', '2020-01-01 09:21:59', 90), (1002, 9001, '2020-01-20 10:01:01', null, null), (1002, 9001, '2020-02-01 12:11:01', null, null), (1003, 9001, '2020-03-01 19:01:01', null, null), (1001, 9001, '2020-03-01 12:01:01', null, null), (1002, 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), (1001, 9002, '2020-02-02 12:01:01', '2020-02-02 12:20:01', 99), (1002, 9002, '2020-02-02 12:01:01', null, null), (1002, 9002, '2020-02-02 12:01:01', '2020-02-02 12:43:01', 81), (1002, 9002, '2020-03-02 12:11:01', null, null), (1001, 9001, '2020-01-02 10:01:01', '2020-01-02 10:31:01', 89), (1001, 9002, '2020-01-01 12:11:01', null, null), (1002, 9001, '2020-01-01 18:01:01', '2020-01-01 18:59:02', 90), (1002, 9003, '2020-05-06 12:01:01', null, null), (1001, 9002, '2020-05-05 18:01:01', null, null); # 第一步,先找出未完成率前50%高的用户ID,注意这里需要的sql试卷 with rote_tab as (select t.uid,t.f_rote,row_number()over(order by t.f_rote desc,uid) as rank2 ,count(t.uid)over(partition by t.tag)as cnt from (select er.uid,ef.tag,(sum(if(submit_time is null,1,0))/count(start_time)) as f_rote from exam_record er left join examination_info ef on ef.exam_id=er.exam_id where tag='SQL' group by uid ) t) select #第四步,分用户和月份进行数据统计;同时需要注意,统计的试卷数是所有类型的,不是之前仅有SQL类型 uid ,start_month ,count(start_time) as total_cnt ,count(submit_time) as complete_cnt from ( select # 第三步,利用窗口函数对每个用户的月份进行降序排序,以便找出最近的三个月; uid ,start_time ,submit_time ,date_format(start_time,'%Y%m') as start_month ,dense_rank()over(partition by uid order by date_format(start_time,'%Y%m') desc) as rank3 from exam_record where uid in (select distinct er.uid from exam_record er left join user_info uf on uf.uid=er.uid where er.uid in (select uid from rote_tab where rank2<=round(cnt/2,0)) and uf.level in (6,7)) # 第二步,进一步找出满足等级为6或7的用户ID ) t2 where rank3<=3 group by uid,start_month order by uid,start_month;

🚀 SQL32 试卷完成数同比2020年的增长率及排名变化

📖 examination_info 表结构 📖 exam_record 表结构

🚀 题目描述 现有试卷信息表examination_info(exam_id试卷ID, tag试卷类别, difficulty试卷难度, duration考试时长, release_time发布时间): +----+---------+--------+------------+----------+---------------------+ | id | exam_id | tag | difficulty | duration | release_time | +----+---------+--------+------------+----------+---------------------+ | 1 | 9001 | SQL | hard | 60 | 2020-01-01 10:00:00 | | 2 | 9002 | C++ | hard | 80 | 2020-01-01 10:00:00 | | 3 | 9003 | 算法 | hard | 80 | 2020-01-01 10:00:00 | | 4 | 9004 | PYTHON | medium | 70 | 2020-01-01 10:00:00 | +----+---------+--------+------------+----------+---------------------+ 试卷作答记录表exam_record(uid用户ID, exam_id试卷ID, start_time开始作答时间, submit_time交卷时间, score得分): +----+------+---------+---------------------+---------------------+-------+ | id | uid | exam_id | start_time | submit_time | score | +----+------+---------+---------------------+---------------------+-------+ | 1 | 1001 | 9001 | 2020-08-02 10:01:01 | 2020-08-02 10:31:01 | 89 | | 2 | 1002 | 9001 | 2020-04-01 18:01:01 | 2020-04-01 18:59:02 | 90 | | 3 | 1001 | 9001 | 2020-04-01 09:01:01 | 2020-04-01 09:21:59 | 80 | | 4 | 1002 | 9003 | 2021-01-20 10:01:01 | 2021-01-20 10:10:01 | 81 | | 5 | 1002 | 9001 | 2021-03-02 19:01:01 | 2021-03-02 19:32:00 | 20 | | 6 | 1001 | 9003 | 2021-04-02 19:01:01 | 2021-04-02 19:40:01 | 89 | | 7 | 1004 | 9004 | 2020-05-02 12:01:01 | 2020-05-02 12:20:01 | 99 | | 8 | 1003 | 9001 | 2021-05-02 12:01:01 | 2021-05-02 12:31:01 | 98 | | 9 | 1001 | 9002 | 2020-02-02 12:01:01 | 2020-02-02 12:20:01 | 99 | | 10 | 1002 | 9002 | 2020-02-02 12:01:01 | 2020-02-02 12:43:01 | 81 | | 11 | 1001 | 9002 | 2020-01-02 19:01:01 | 2020-01-02 19:59:01 | 69 | | 12 | 1001 | 9004 | 2021-09-02 12:11:01 | NULL | NULL | | 13 | 1003 | 9001 | 2020-01-02 10:01:01 | 2020-01-02 10:31:01 | 89 | | 14 | 1002 | 9004 | 2020-01-01 12:11:01 | 2020-01-01 12:31:01 | 83 | | 15 | 1002 | 9003 | 2021-01-01 18:01:01 | 2021-01-01 18:59:02 | 90 | | 16 | 1002 | 9002 | 2020-02-02 12:01:01 | NULL | NULL | | 17 | 1002 | 9002 | 2020-03-02 12:11:01 | NULL | NULL | | 18 | 1001 | 9002 | 2021-05-05 18:01:01 | NULL | NULL | +----+------+---------+---------------------+---------------------+-------+ 请计算2021年上半年各类试卷的做完次数相比2020年上半年同期的增长率(百分比格式,保留1位小数), 以及做完次数排名变化,按增长率和21年排名降序输出。 由示例数据结果输出如下: +------+-------------+-------------+-------------+------------------+------------------+------------+ | tag | exam_cnt_20 | exam_cnt_21 | growth_rate | exam_cnt_rank_20 | exam_cnt_rank_21 | rank_delta | +------+-------------+-------------+-------------+------------------+------------------+------------+ | SQL | 3 | 2 | -33.3% | 1 | 2 | 1 | +------+-------------+-------------+-------------+------------------+------------------+------------+ 🚀 建表语句 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); 🍌🍌 答案 with info_2020 as ( select ei.tag, count(er.score) as exam_cnt ,rank() over(order by count(er.score) desc) as exam_cnt_rank from exam_record as er right join examination_info as ei on er.exam_id=ei.exam_id where year(er.start_time)=2020 and month(er.start_time)<=6 group by ei.tag having count(er.score)>0), info_2021 as ( select ei.tag, count(er.score) as exam_cnt ,rank() over(order by count(er.score) desc) as exam_cnt_rank from exam_record as er right join examination_info as ei on er.exam_id=ei.exam_id where year(er.start_time)=2021 and month(er.start_time)<=6 group by ei.tag having count(er.score)>0), exam_year_info as ( select i20.tag, i20.exam_cnt as exam_cnt_20, i21.exam_cnt as exam_cnt_21, i20.exam_cnt_rank as exam_cnt_rank_20, i21.exam_cnt_rank as exam_cnt_rank_21 from info_2020 as i20 join info_2021 as i21 on i20.tag=i21.tag) select tag, exam_cnt_20, exam_cnt_21, concat(round((exam_cnt_21-exam_cnt_20)/exam_cnt_20*100, 1), '%') as growth_rate, exam_cnt_rank_20, exam_cnt_rank_21, (cast(exam_cnt_rank_21 as signed)-cast(exam_cnt_rank_20 as signed)) as rank_delta from exam_year_info order by growth_rate desc, exam_cnt_rank_21 desc;

5.2 🌈 聚合窗口函数 🚀 SQL33 对试卷得分做min-max归一化

📖 examination_info 表结构 📖 exam_record 表结构

🚀 题目描述 现有试卷信息表examination_info(exam_id试卷ID, tag试卷类别, difficulty试卷难度, duration考试时长, release_time发布时间): +----+---------+--------+------------+----------+---------------------+ | id | exam_id | tag | difficulty | duration | release_time | +----+---------+--------+------------+----------+---------------------+ | 1 | 9001 | SQL | hard | 60 | 2020-01-01 10:00:00 | | 2 | 9002 | C++ | hard | 80 | 2020-01-01 10:00:00 | | 3 | 9003 | 算法 | hard | 80 | 2020-01-01 10:00:00 | | 4 | 9004 | PYTHON | medium | 70 | 2020-01-01 10:00:00 | | 5 | 9005 | WEB | hard | 80 | 2020-01-01 10:00:00 | | 6 | 9006 | PYTHON | hard | 80 | 2020-01-01 10:00:00 | | 7 | 9007 | web | hard | 80 | 2020-01-01 10:00:00 | | 8 | 9008 | Web | medium | 70 | 2020-01-01 10:00:00 | | 9 | 9009 | WEB | medium | 70 | 2020-01-01 10:00:00 | | 10 | 9010 | SQL | medium | 70 | 2020-01-01 10:00:00 | +----+---------+--------+------------+----------+---------------------+ 试卷作答记录表exam_record(uid用户ID, exam_id试卷ID, start_time开始作答时间, submit_time交卷时间, score得分): +----+------+---------+---------------------+---------------------+-------+ | id | uid | exam_id | start_time | submit_time | score | +----+------+---------+---------------------+---------------------+-------+ | 1 | 1001 | 9001 | 2020-01-01 09:01:01 | 2020-01-01 09:21:59 | 90 | | 2 | 1003 | 9002 | 2020-01-01 19:01:01 | 2020-01-01 19:30:01 | 75 | | 3 | 1004 | 9002 | 2020-01-01 12:01:01 | 2020-01-01 12:11:01 | 60 | | 4 | 1003 | 9002 | 2020-01-01 12:01:01 | 2020-01-01 12:41:01 | 90 | | 5 | 1002 | 9002 | 2020-01-02 19:01:01 | 2020-01-02 19:32:00 | 90 | | 6 | 1003 | 9001 | 2020-01-02 12:01:01 | 2020-01-02 12:31:01 | 68 | | 7 | 1001 | 9002 | 2020-01-02 12:01:01 | 2020-01-02 12:43:01 | 81 | | 8 | 1001 | 9005 | 2020-01-02 12:11:01 | NULL | NULL | | 9 | 1001 | 9001 | 2020-01-02 10:01:01 | 2020-01-02 10:31:01 | 89 | | 10 | 1002 | 9002 | 2020-01-01 12:11:01 | 2020-01-01 12:31:01 | 83 | | 11 | 1002 | 9004 | 2021-09-06 12:01:01 | NULL | NULL | | 12 | 1002 | 9002 | 2021-05-05 18:01:01 | NULL | NULL | +----+------+---------+---------------------+---------------------+-------+ 在物理学及统计学数据计算时,有个概念叫min-max标准化,也被称为离差标准化,是对原始数据的线性变换,使结果值映射到[0 - 1]之间。 请你将用户作答高难度试卷的得分在每份试卷作答记录内执行min-max归一化后缩放到[0,100]区间,并输出用户ID、试卷ID、归一化后分数平均值; 最后按照试卷ID升序、归一化分数降序输出。(注:得分区间默认为[0,100], 如果某个试卷作答记录中只有一个得分,那么无需使用公式,归一化并缩放后分数仍为原分数)。 由示例数据结果输出如下: +------+---------+------+ | uid | exam_id | sc1 | +------+---------+------+ | 1001 | 9001 | 98 | | 1003 | 9001 | 0 | | 1002 | 9002 | 88 | | 1003 | 9002 | 75 | | 1001 | 9002 | 70 | | 1004 | 9002 | 0 | +------+---------+------+ 解释:高难度试卷有9001、9002、9003; 作答了9001的记录有3条,分数分别为68、89、90,按给定公式归一化后分数为:0、95、100, 而后两个得分都是用户1001作答的,因此用户1001对试卷9001的新得分为(95+100)/2≈98(只保留整数部分), 用户1003对于试卷9001的新得分为0。最后结果按照试卷ID升序、归一化分数降序输出。 🚀 建表语句 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((score-min_score)/(max_score-min_score)*100)) sc1 from( SELECT ex.uid,ex.exam_id,score, max(score) over(partition by ex.exam_id ) max_score, min(score) over(partition by ex.exam_id ) min_score from exam_record ex join examination_info e on ex.exam_id=e.exam_id where difficulty='hard' and score is not null) a where max_score!=min_score group by uid,exam_id union select uid,exam_id,score sc1 from( SELECT ex.uid,ex.exam_id,score, max(score) over(partition by ex.exam_id ) max_score, min(score) over(partition by ex.exam_id ) min_score from exam_record ex join examination_info e on ex.exam_id=e.exam_id where difficulty='hard' and score is not null) b where max_score=min_score order by exam_id,sc1 desc;

🚀 SQL34 每份试卷每月作答数和截止当月的作答总数

📖 exam_record 表结构

🚀 题目描述 现有试卷作答记录表exam_record(uid用户ID, exam_id试卷ID, start_time开始作答时间, submit_time交卷时间, score得分): 请输出每份试卷每月作答数和截止当月的作答总数。 由示例数据结果输出如下: +---------+-------------+-----------+--------------+ | exam_id | start_month | month_cnt | cum_exam_cnt | +---------+-------------+-----------+--------------+ | 9001 | 202001 | 2 | 2 | | 9001 | 202002 | 1 | 3 | | 9001 | 202003 | 3 | 6 | | 9001 | 202005 | 1 | 7 | | 9002 | 202001 | 1 | 1 | | 9002 | 202002 | 3 | 4 | | 9002 | 202003 | 1 | 5 | +---------+-------------+-----------+--------------+ 解释:试卷9001在202001、202002、202003、202005共4个月有被作答记录, 每个月被作答数分别为2、1、3、1,截止当月累积作答总数为2、3、6、7。 🚀 建表语句 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, DATE_FORMAT(start_time,'%Y%m') start_month, COUNT(DATE_FORMAT(start_time,'%Y%m')) AS month_cnt, SUM(COUNT(DATE_FORMAT(start_time,'%Y%m'))) over (partition by exam_id order by DATE_FORMAT(start_time,'%Y%m')) cum_exam_cnt FROM exam_record GROUP BY exam_id, start_month ORDER BY exam_id, start_month;

🚀 SQL35 每月及截止当月的答题情况

📖 exam_record 表结构

🚀 题目描述 现有试卷作答记录表exam_record(uid用户ID, exam_id试卷ID, start_time开始作答时间, submit_time交卷时间, score得分): +----+------+---------+---------------------+---------------------+-------+ | id | uid | exam_id | start_time | submit_time | score | +----+------+---------+---------------------+---------------------+-------+ | 1 | 1001 | 9001 | 2020-01-01 09:01:01 | 2020-01-01 09:21:59 | 90 | | 2 | 1002 | 9001 | 2020-01-20 10:01:01 | 2020-01-20 10:10:01 | 89 | | 3 | 1002 | 9001 | 2020-02-01 12:11:01 | 2020-02-01 12:31:01 | 83 | | 4 | 1003 | 9001 | 2020-03-01 19:01:01 | 2020-03-01 19:30:01 | 75 | | 5 | 1004 | 9001 | 2020-03-01 12:01:01 | 2020-03-01 12:11:01 | 60 | | 6 | 1003 | 9001 | 2020-03-01 12:01:01 | 2020-03-01 12:41:01 | 90 | | 7 | 1002 | 9001 | 2020-05-02 19:01:01 | 2020-05-02 19:32:00 | 90 | | 8 | 1001 | 9002 | 2020-01-02 19:01:01 | 2020-01-02 19:59:01 | 69 | | 9 | 1004 | 9002 | 2020-02-02 12:01:01 | 2020-02-02 12:20:01 | 99 | | 10 | 1003 | 9002 | 2020-02-02 12:01:01 | 2020-02-02 12:31:01 | 68 | | 11 | 1001 | 9002 | 2020-02-02 12:01:01 | 2020-02-02 12:43:01 | 81 | | 12 | 1001 | 9002 | 2020-03-02 12:11:01 | NULL | NULL | +----+------+---------+---------------------+---------------------+-------+ 请输出自从有用户作答记录以来,每月的试卷作答记录中月活用户数、新增用户数、截止当月的单月最大新增用户数、截止当月的累积用户数。 结果按月份升序输出。由示例数据结果输出如下: +--------+-----+--------------+------------------+------------+ | stime | mau | month_add_uv | max_month_add_uv | cum_sum_uv | +--------+-----+--------------+------------------+------------+ | 202001 | 2 | 2 | 2 | 2 | | 202002 | 4 | 2 | 2 | 4 | | 202003 | 3 | 0 | 2 | 4 | | 202005 | 1 | 0 | 2 | 4 | +--------+-----+--------------+------------------+------------+ 🚀 建表语句 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 stime,mau,if(month_add is not null,month_add,0) as month_add_uv, max(if(month_add is not null, month_add,0)) over (order by stime) as max_month_add_uv, sum(if(month_add is not null, month_add,0)) over (order by stime) as cum_sum_uv FROM (SELECT stime, count(distinct uid) as mau FROM (SELECT uid,DATE_FORMAT(start_time,'%Y%m') as stime FROM exam_record) a GROUP BY stime) c LEFT JOIN (SELECT ntime, count(distinct uid) as month_add FROM (SELECT uid,min(DATE_FORMAT(start_time,'%Y%m')) as ntime from exam_record GROUP BY uid) b GROUP BY ntime) d ON c.stime=d.ntime;

体系化学习SQL,请到经典高频面试题库,参加实训,提高你的SQL技能吧~

https://·/link/pc_csdncpt_itbd_sql


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #SQL #牛客