持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第 14 天,点击查看活动详情
文章首发地址:村雨遥
SQL11 删除表
描述
现有一张试卷作答记录表exam_record,其中包含多年来的用户作答试卷记录。一般每年都会为exam_record表建立一张备份表exam_record_{YEAR},{YEAR}为对应年份。
问题
现在随着数据越来越多,存储告急,请你把很久前的(2011到2014年)备份表都删掉(如果存在的话)。
示例
输入:
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);
输出:
exam_record_2010
exam_record_2015
解答
根据题意可知,2011 - 2014 的备份表的表名分别是:
exam_record_2011exam_record_2012exam_record_2013exam_record_2014
要删除一个表,需要用到 DROP TABLE 语句,此外,题意说了如果存在备份表才删除,所以我们需要加入关键字 IF EXISTS,其语法如下,接着套用到本题就可以得到答案。
DROP TABLE [IF EXISTS] [数据表];
DROP TABLE IF EXISTS
exam_record_2011, exam_record_2012, exam_record_2013, exam_record_2014;
SQL12 创建索引
描述
现有一张试卷信息表examination_info,其中包含各种类型试卷的信息。
问题
为了对表更方便快捷地查询,需要在examination_info表创建以下索引,规则如下:
在duration列创建普通索引idx_duration、在exam_id列创建唯一性索引uniq_idx_exam_id、在tag列创建全文索引full_idx_tag。
根据题意,将返回如下结果:
| examination_info | 0 | PRIMARY | 1 | id | A | 0 | BTREE | |||
|---|---|---|---|---|---|---|---|---|---|---|
| examination_info | 0 | uniq_idx_exam_id | 1 | exam_id | A | 0 | YES | BTREE | ||
| examination_info | 1 | idx_duration | 1 | duration | A | 0 | BTREE | |||
| examination_info | 1 | 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;
输出:
examination_info|0|PRIMARY|1|id|A|0|None|None||BTREE|||YES|None
examination_info|0|exam_id|1|exam_id|A|0|None|None||BTREE|||YES|None
examination_info|0|uniq_idx_exam_id|1|exam_id|A|0|None|None||BTREE|||YES|None
examination_info|1|idx_duration|1|duration|A|0|None|None||BTREE|||YES|None
examination_info|1|full_idx_tag|1|tag|None|0|None|None|YES|FULLTEXT|||YES|None
解答
索引有三种,一种是普通索引,其创建方式如下:
CREATE INDEX [索引名] ON [数据表名]([列名]);
第二种是唯一索引,其创建方式如下:
CREATE UNIQUE INDEX [索引名] ON [数据表名]([列名]);
第三种是创建全文索引,其创建方式如下:
CREATE FULLTEXT INDEX [索引名] ON [数据表名]([列名]);
根据题意,得到最终的解答结果如下:
CREATE INDEX idx_duration ON examination_info(duration);
CREATE UNIQUE INDEX uniq_idx_exam_id ON examination_info(exam_id);
CREATE FULLTEXT INDEX full_idx_tag ON examination_info(tag);
SQL13 删除索引
描述
根据上题,完成以下问题。
问题
请删除examination_info表上的唯一索引uniq_idx_exam_id和全文索引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 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);
复制
输出:
examination_info|0|PRIMARY|1|id|A|0|None|None||BTREE|||YES|None
examination_info|1|idx_duration|1|duration|A|0|None|None||BTREE|||YES|None
解答
主要有两种方式,第一种是通过 DROP 的方式,其语法如下:
DROP INDEX [索引名] ON [数据表名];
DROP INDEX uniq_idx_exam_id ON examination_info;
DROP INDEX full_idx_tag ON examination_info;
第二种是通过 ALTER 的方式,其语法如下:
ALTER TABLE [数据表名] DROP INDEX [索引名];
ALTER TABLE examination_info DROP INDEX uniq_idx_exam_id;
ALTER TABLE examination_info DROP INDEX full_idx_tag;
SQL14 SQL类别高难度试卷得分的截断平均值
描述
牛客的运营同学想要查看大家在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-09-07 12:01:01 | 2021-09-07 10:31:01 | 50 |
| 10 | 1004 | 9001 | 2021-09-06 10:01:01 | (NULL) | (NULL) |
问题
请你帮她从exam_record数据表中计算所有用户完成SQL类别高难度试卷得分的截断平均值(去掉一个最大值和一个最小值后的平均值)。
根据输入你的查询结果如下:
| tag | difficulty | clip_avg_score |
|---|---|---|
| SQL | hard | 81.7 |
从examination_info表可知,试卷9001为高难度SQL试卷,该试卷被作答的得分有[80,81,84,90,50],去除最高分和最低分后为[80,81,84],平均分为81.6666667,保留一位小数后为81.7
输入描述:
输入数据中至少有3个有效分数
示例
输入:
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);
输出:
SQL|hard|81.7
解答
要求除开最大最小值后的平均值,这里需要用到聚合函数 SUM()、MAX()、MIN() 等,其次,为了统计记录数,需要用到 COUNT() 函数。
要保留平均分的 1 位小数,所以可以用 ROUND() 函数。
其次,要筛选出对应难度为 hard,标签为 SQL 的记录,需要用到 WHERE 筛选,并用 AND 将两个条件串联。
最后,依照题意将上边的细节问题一组合即可。
SELECT tag, difficulty,
ROUND((SUM(score) - MAX(score) - MIN(score)) / (COUNT(score) - 2), 1)
AS clip_avg_score
FROM exam_record
JOIN examination_info USING(exam_id)
WHERE
tag = "SQL" AND difficulty="hard"
SQL15 统计作答次数
描述
有一个试卷作答记录表exam_record。
| 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 | 88 |
| 11 | 1004 | 9001 | 2021-09-06 12:01:01 | (NULL) | (NULL) |
问题
请从中统计出总作答次数total_pv、试卷已完成作答数complete_pv、已完成的试卷数complete_exam_cnt。
示例数据 exam_record表(uid用户ID, exam_id试卷ID, start_time开始作答时间, submit_time交卷时间, score得分)。
示例输出:
| total_pv | complete_pv | complete_exam_cnt |
|---|---|---|
| 11 | 7 | 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, '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);
输出:
11|7|2
解答
要统计总作答词数、试卷已完成作答数、已完成的试卷数,都只要用一个聚合函数 COUNT(),它会忽略所统计列中值为 NULL 的行。
而针对已完成的试卷数,需要用到 IF 来判断。同时,一套试卷可能会被完成很多次,所以需要去用到 DISTINCT 去重。
SELECT
COUNT(exam_id) AS total_pv,
COUNT(submit_time) AS complete_pv,
COUNT(DISTINCT IF(submit_time IS NOT NULL, exam_id, NULL)) AS complete_exam_cnt
FROM exam_record;