0
点赞
收藏
分享

微信扫一扫

SQL 进阶挑战篇

RJ_Hwang 2022-02-26 阅读 81

01 增删改操作

插入记录

SQL1 插入记录(一)

现在有两个用户的作答记录详情如下:

  • 用户1001在2021年9月1日晚上10点11分12秒开始作答试卷9001,并在50分钟后提交,得了90分;
  • 用户1002在2021年9月4日上午7点1分2秒开始作答试卷9002,并在10分钟后退出了平台。

请用一条语句将这两条记录插入表中。

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 插入记录(二)

将2021年之前的已完成了的试题作答纪录导入到exam_record_before_2021表来备份2021年之前的试题作答记录。

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 插入记录(三)

将 2021-01-01 00:00:00 作为发布时间插入到试题信息表examination_info,不管该ID试卷是否存在,都要插入成功。

REPLACE INTO examination_info
(id, exam_id, tag, difficulty, duration, release_time)
VALUES(null, 9003, 'SQL', 'hard', 90, '2021-01-01 00:00:00')

更新记录

SQL4 更新记录(一)

把examination_info表中tag为PYTHON的tag字段全部修改为Python。

UPDATE examination_info
SET tag ='Python' WHERE tag='PYTHON'

SQL5 更新记录(二)

把exam_record表中2021年9月1日之前开始作答的未完成记录全部改为被动完成,即:将完成时间改为'2099-01-01 00:00:00',分数改为 0。

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

删除记录

SQL6 删除记录(一)

删除exam_record表中作答时间小于5分钟整且分数不及格(及格线为60分)的记录。

DELETE FROM exam_record
WHERE timestampdiff(minute,start_time,submit_time) < 5 AND score < 60

SQL7 删除记录(二)

删除exam_record表中未完成作答或作答时间小于5分钟整的记录中,开始作答时间最早的3条记录。

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表中所有记录,并重置自增主键。

TRUNCATE TABLE exam_record;

02 表与索引操作

表的创建、修改与删除

SQL9 创建一张新表

创建一张优质用户信息表user_info_vip,表结构和用户信息表一致。

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 修改表

在用户信息表,字段level的后面增加一列最多可保存15个汉字的字段school;并将表中job列名改为profession,同时varchar字段长度变为10;achievement的默认值设置为 0。

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 删除表

删掉(如果存在)(2011到2014年)备份表。

DROP TABLE
IF EXISTS
exam_record_2011,
exam_record_2012,
exam_record_2013,
exam_record_2014;

索引的创建、删除

SQL12 创建索引

为了对表更方便快捷地查询,需要在examination_info表创建以下索引,规则如下:

在duration列创建普通索引idx_duration、在exam_id列创建唯一性索引uniq_idx_exam_id、在tag列创建全文索引full_idx_tag。

# 唯一索引
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。

DROP index uniq_idx_exam_id ON examination_info;
DROP index full_idx_tag ON examination_info;

03 聚合分组查询

聚合函数

SQL14 SQL类别高难度试卷得分的截断平均值

从exam_record数据表中计算所有用户完成SQL类别高难度试卷得分的截断平均值(去掉一个最大值和一个最小值后的平均值)。

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 统计作答次数

从表中统计出总作答次数total_pv、试卷已完成作答数complete_pv、已完成的试卷数complete_exam_cnt。

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 得分不小于平均分的最低分

从表中找到SQL试卷得分不小于该类试卷平均得分的用户最低得分。

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'
);

分组查询

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

计算2021年每个月里试卷作答区用户平均月活跃天数avg_active_days和月度活跃人数mau。

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 月总刷题数和日均刷题数

统计出2021年每个月里用户的月总刷题数month_q_cnt 和日均刷题数avg_day_q_cnt(按月份升序排序)以及该年的总体情况。

SELECT ifnull(a.ymd, '2021汇总'), COUNT(1), ROUND(COUNT(1) / max(da), 3)
FROM (
    SELECT DATE_FORMAT(submit_time, '%Y%m') ymd, 
    DAYOFMONTH(last_day(submit_time)) da
    FROM  practice_record 
    WHERE  year(submit_time) = '2021' 
) a
GROUP BY a.ymd WITH ROLLUP

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

04 多表查询

嵌套子查询

SQL20 月均完成试卷数不小于3的用户爱作答的类别

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

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

合并查询

SQL23 每个题目和每份试卷被作答的人数和次数

SQL24 分别满足两个活动的人

连接查询

SQL25 满足条件的用户的试卷完成数和题目练习数

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

05 窗口函数

专用窗口函数

SQL27 每类试卷得分前3名

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

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

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

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

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

聚合窗口函数

SQL33 对试卷得分做min-max归一化

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

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

06 其他常用操作

空值处理

SQL36 统计有未完成状态的试卷的未完成数和未完成率

SQL37 0级用户高难度试卷的平均用时和平均得分

高级条件语句

SQL38 筛选限定昵称成就值活跃日期的用户

SQL39 筛选昵称规则和试卷规则的作答记录

SQL40 根据指定记录是否存在输出不同情况

SQL41 各用户等级的不同得分表现占比

限量查询

SQL42 注册时间最早的三个人

SQL43 注册当天就完成了试卷的名单第三页

文本转换函数

SQL44 修复串列了的记录

SQL45 对过长的昵称截取处理

SQL46 大小写混乱时的筛选统计

举报

相关推荐

0 条评论