牛客网SQL进阶137:第二快/慢用时之差大于试卷时长一半的试卷

官网链接:

第二快慢用时之差大于试卷时长一半的试卷_牛客题霸_牛客网现有试卷信息表examination_info(exam_id试卷ID, tag试卷类别,。题目来自【牛客题霸】https://www.nowcoder.com/practice/b1e2864271c14b63b0df9fc08b559166?tpId=240

0 问题描述

  • 试卷信息表examination_info(exam_id试卷ID, tag试卷类别, difficulty试卷难度, duration考试时长, release_time发布时间)
  • 试卷作答记录表exam_record(uid用户ID, exam_id试卷ID, start_time开始作答时间, submit_time交卷时间, score得分)
  • 试卷信息表examination_info和试卷作答记录表exam_record, 找到第二快和第二慢用时之差大于试卷时长的一半的试卷信息,按试卷ID降序排序

1 数据准备

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

2 数据分析

完整的代码如下:

sql 复制代码
select distinct exam_id,
                duration,
                release_time
from(select exam_id,
            duration,
            release_time,
            sum(case when rn1 =2 then difftime
                 when rn2 =2 then -difftime
                 else 0
                 end ) as sub
    from(select
               exam_id,
               duration,
               release_time,
               difftime,
               row_number() over(partition  by exam_id order by difftime desc ) as rn1,
               row_number() over(partition  by exam_id order by difftime ) as rn2
        from (select
                   er.exam_id,
                   ei.duration,
                   ei.release_time,
                   timestampdiff(minute,er.start_time,er.submit_time) as difftime
              from exam_record er  join examination_info ei
              on  er.exam_id = ei.exam_id
              where submit_time is not null)tmp1
         )tmp2
    group by exam_id
    )tmp3
  where sub * 2 >= duration
   order by exam_id desc;

上述的解题步骤拆分

step1:求出各试卷的用时之差,并进行正序、逆序排序

step2:求出第二快和第二慢的用时之差,并和试卷规定时长(duration)进行比对

step3:试卷ID降序排序

步骤代码

step1:

sql 复制代码
select
      exam_id,
      duration,
      release_time,
      difftime,
      --进行正序、逆序排序
      row_number() over(partition  by exam_id order by difftime desc ) as rn1,
      row_number() over(partition  by exam_id order by difftime ) as rn2
from (select
           er.exam_id,
           ei.duration,
           ei.release_time,
           --step1:求出各试卷的用时之差timestampdiff,并进行正序、逆序排序
           timestampdiff(minute,er.start_time,er.submit_time) as difftime
      from exam_record er  join examination_info ei
      on  er.exam_id = ei.exam_id
      where submit_time is not null)tmp1;

step2: 使用 case when进行赋值, 当rn1 =2 时,代表是第二快的difftime(取正值);当rn2 =2 时,代表是第二慢的difftime(需要取负值); 外层再嵌套sum聚合函数,即得到第二快和第二慢的用时之差sub

sql 复制代码
select exam_id,
       duration,
       release_time,
        sum(case when rn1 =2 then difftime
                 when rn2 =2 then -difftime
                 else 0
                 end ) as sub
from(select
             exam_id,
             duration,
             release_time,
             difftime,
             row_number() over(partition  by exam_id order by difftime desc ) as rn1,
             row_number() over(partition  by exam_id order by difftime ) as rn2
    from (select
                er.exam_id,
                ei.duration,
                ei.release_time,
                timestampdiff(minute,er.start_time,er.submit_time) as difftime
           from exam_record er  join examination_info ei
            on  er.exam_id = ei.exam_id
             where submit_time is not null)tmp1
        )tmp2
 group by exam_id;

**step3:**sub和试卷规定时长(duration)进行比对,要求:sub * 2 >= duration

sql 复制代码
select distinct exam_id,
                duration,
                release_time
from(select exam_id,
            duration,
            release_time,
            sum(case when rn1 =2 then difftime
                 when rn2 =2 then -difftime
                 else 0
                 end ) as sub
    from(select
               exam_id,
               duration,
               release_time,
               difftime,
               row_number() over(partition  by exam_id order by difftime desc ) as rn1,
               row_number() over(partition  by exam_id order by difftime ) as rn2
        from (select
                   er.exam_id,
                   ei.duration,
                   ei.release_time,
                   timestampdiff(minute,er.start_time,er.submit_time) as difftime
              from exam_record er  join examination_info ei
              on  er.exam_id = ei.exam_id
              where submit_time is not null)tmp1
         )tmp2
    group by exam_id
    )tmp3
  where sub * 2 >= duration
   order by exam_id desc;

3 小结

上述案例用到的知识点:

(1)timestampdiff函数

timestampdiff: MySQL 中用来计算两个日期或时间之间的差值的函数;

语法:timestampdiff(unit, start_date, end_date)

参数说明:

unit: 差值的单位,可以是second(秒)、minute(分)、hour(小时)、day(天)、week(周)、month(月)、quarter(季度)或 year(年)。

start_date:表示时间段的起始时间

end_date:表示时间段的结束时间

(2)row_number() over(partition by ..order by ..desc)窗口函数

(3)sum +case when :条件+聚合

相关推荐
joke_xiaoli1 小时前
如何重置 MySQL root 用户的登录密码?
数据库·mysql
winner88811 小时前
Hive SQL 精进系列:字符串拼接的三种常用方式
hive·hadoop·sql
鹏说大数据2 小时前
MySQL连接较慢原因分析及解决措施
数据库·mysql
极限实验室3 小时前
使用 INFINI Gateway 保护 Elasticsearch 集群之修改查询不合理参数(二)
数据库
竹杖芒鞋轻胜马,谁怕?一蓑烟雨任平生。4 小时前
etcd客户化工具
数据库·etcd
谷晓光4 小时前
python中print函数的flush如何使用
linux·服务器·数据库
OceanBase数据库官方博客4 小时前
自然语言秒转SQL—— 免费体验 OB Cloud Text2SQL 数据查询
数据库·sql·ai·oceanbase·分布式数据库·向量·text2sql
Stark、4 小时前
【MySQL】多表查询(笛卡尔积现象,联合查询、内连接、左外连接、右外连接、子查询)-通过练习快速掌握法
数据库·后端·sql·mysql
yqcoder4 小时前
Redis 的应用场景
数据库·redis·缓存
kngines4 小时前
【实战ES】实战 Elasticsearch:快速上手与深度实践-8.2.2成本优化与冷热数据分离
大数据·数据库·elasticsearch·搜索引擎