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

描述

现有试卷信息表examination_info(exam_id试卷ID, tag试卷类别, difficulty试卷难度, duration考试时长, release_time发布时间):

试卷作答记录表exam_record(uid用户ID, exam_id试卷ID, start_time开始作答时间, submit_time交卷时间, score得分):

找到第二快和第二慢用时之差大于等于试卷时长的一半的试卷信息,按试卷ID降序排序。由示例数据结果输出如下:

|---------|----------|---------------------|
| exam_id | duration | release_time |
| 9001 | 60 | 2021-09-01 06:00:00 |

解释:试卷9001被作答用时有58分钟、50分钟、30分1秒、11分钟、10分钟,第二快和第二慢用时之差为50分钟-11分钟=39分钟,试卷时长为60分钟,因此满足大于试卷时长一半的条件,输出试卷ID、时长、发布时间。

复制代码
select
    exam_id,
    duration,
    release_time
from
    (
        select
            exam_id,
            duration,
            release_time,
            sum(
                case
                    when rk_desc = 2 then time_diff
                    when rk_asc = 2 then - time_diff
                    else 0
                end
            ) as timre
        from
            (
                select
                    a.exam_id,
                    timestampdiff(minute, b.start_time, b.submit_time) time_diff,
                    a.duration,
                    a.release_time,
                    row_number() over (
                        partition by
                            a.exam_id
                        order by
                            timestampdiff(minute, b.start_time, b.submit_time) desc
                    ) as rk_desc,
                    row_number() over (
                        partition by
                            a.exam_id
                        order by
                            timestampdiff(minute, b.start_time, b.submit_time) asc
                    ) as rk_asc
                from
                    examination_info a
                    join exam_record b on a.exam_id = b.exam_id
                where
                    b.submit_time is not null
            ) t1
        group by
            exam_id
    ) t2
where
    timre >= (duration / 2)
order by
    exam_id desc;

关键 SQL 逻辑拆解

✅ 第一步:计算每位考生的答题时长(分钟)
复制代码
timestampdiff(minute, start_time, submit_time) as time_diff
  • 使用 TIMESTAMPDIFF(MINUTE, ...) 计算答题持续时间。
✅ 第二步:对每场考试分别排序,找出"第二长"和"第二短"
复制代码
row_number() over (
    partition by exam_id 
    order by time_diff desc
) as rk_desc  -- 从长到短:最长是1,第二长是2

row_number() over (
    partition by exam_id 
    order by time_diff asc
) as rk_asc   -- 从短到长:最短是1,第二短是2
  • 利用窗口函数 ROW_NUMBER() 实现排名。
  • 注意:rk_desc=2 表示第二慢提交(答题时间第二长)。
✅ 第三步:条件聚合,提取"第二长 - 第二短"时间差
复制代码
sum(
    case 
        when rk_desc = 2 then time_diff
        when rk_asc = 2 then -time_diff
        else 0 
    end
) as timre
  • 巧妙利用 sum(case ...) 实现"提取特定排名值"的效果。
  • 最终结果:timre = 第二长答题时间 - 第二短答题时间

💡 技巧提示:这种"条件求和"是 SQL 中实现"取第 N 值"的常用技巧。

✅ 第四步:筛选满足条件的考试
复制代码
where timre >= (duration / 2)
  • 只保留差异较大的考试。
✅ 第五步:输出并排序
复制代码
select exam_id, duration, release_time
order by exam_id desc
相关推荐
毕设十刻14 小时前
基于vue的考研信息系统6kv17(程序 + 源码 + 数据库 + 调试部署 + 开发环境配置),配套论文文档字数达万字以上,文末可获取,系统界面展示置于文末
前端·数据库·vue.js
龙茶清欢14 小时前
PostgreSQL 和 MySQL两个数据库的索引的区别
数据库·mysql·postgresql
望获linux15 小时前
论文解读:利用中断隔离技术的 Linux 亚微秒响应性能优化
java·linux·运维·前端·arm开发·数据库·性能优化
柱子jason15 小时前
使用IOT-Tree消息流InfluxDB模块节点实现标签数据的时序数据库存储
数据库·物联网·时序数据库·influxdb·iot-tree
TDengine (老段)15 小时前
TDengine 聚合函数 ELAPSED 用户手册
java·大数据·数据库·sql·物联网·时序数据库·tdengine
TDengine (老段)15 小时前
TDengine 聚合函数 HYPERLOGLOG 用户手册
大数据·数据库·物联网·哈希算法·时序数据库·iot·tdengine
Elastic 中国社区官方博客15 小时前
使用 Elasticsearch 构建 AI Agentic 工作流
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
kobe_OKOK_15 小时前
django 使用绑定多个数据库实现数据的同步
数据库·python·django
麦兜*16 小时前
Spring Boot 项目 Docker 化:从零到一的完整实战指南
数据库·spring boot·redis·后端·spring·缓存·docker
zl97989916 小时前
MySQL-数据库日志
数据库·mysql·database