网络知识 娱乐 牛客刷题-SQL进阶挑战大总结(细节狂魔)

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

📢📢📢📣📣📣
哈喽!大家好,我是【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表,现在有两个用户的作答记录详情如下:
用户1001202191日晚上101112秒开始作答试卷9001,并在50分钟后提交,得了90分;
用户1002202194日上午712秒开始作答试卷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表中202191日之前开始作答的未完成记录全部改为被动完成,
即:将完成时间改为'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