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
相关推荐
OceanRoy5 小时前
数据库表的设计
数据库·内连接·外连接·er图·表的约束·三大范式·多表连接
Pniubi6 小时前
怎么排查慢SQL,怎么解决?
java·数据库·sql
Decay__10 小时前
VMware 安装 SQL Server 双节点 AlwaysOn 可用性组教程 —— WSFC、AG 与侦听器完整部署(系列核心篇)
运维·数据库·sql·mysql·架构
茶栀(*´I`*)11 小时前
SQL 性能分析:从慢查询日志到执行计划的完整定位方法
数据库·sql
艺杯羹11 小时前
1Panel 装好后 ufw 仍是 inactive:一次服务器安全盲区复盘
服务器·数据库·安全·网络安全·系统架构·实战·1panel
code2cat12 小时前
【随笔】MCP工具重试:任务已经创建,响应丢了怎么办
数据库·mcp
wuyk55514 小时前
Spider-第10讲-SQLite持久化与去重
数据库·爬虫·sqlite
乌暮15 小时前
Spring AOP 与 Spring 事务:用大白话彻底理解原理与实践
java·数据库·spring boot·后端·sql·学习·spring
小此方16 小时前
Re:Mysql数据库基础篇(十二):什么是事务、事务解决了什么问题、事务的四大属性、事务的操作方式
数据库·mysql
flash俊杰17 小时前
v0.5-01 让桌面 AI 助手记得住:预算组装、递归摘要、长期记忆与评估基线
数据库·安全·架构