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、时长、发布时间。
selectexam_id,duration,release_time
from(selectexam_id,duration,release_time,sum(casewhen rk_desc = 2 then time_diffwhen rk_asc = 2 then - time_diffelse 0end) as timrefrom(selecta.exam_id,timestampdiff(minute, b.start_time, b.submit_time) time_diff,a.duration,a.release_time,row_number() over (partition bya.exam_idorder bytimestampdiff(minute, b.start_time, b.submit_time) desc) as rk_desc,row_number() over (partition bya.exam_idorder bytimestampdiff(minute, b.start_time, b.submit_time) asc) as rk_ascfromexamination_info ajoin exam_record b on a.exam_id = b.exam_idwhereb.submit_time is not null) t1group byexam_id) t2
wheretimre >= (duration / 2)
order byexam_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,第二长是2row_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_diffwhen rk_asc = 2 then -time_diffelse 0 end
) as timre
- 巧妙利用
sum(case ...)
实现“提取特定排名值”的效果。 - 最终结果:
timre = 第二长答题时间 - 第二短答题时间
💡 技巧提示:这种“条件求和”是 SQL 中实现“取第 N 值”的常用技巧。
✅ 第四步:筛选满足条件的考试
where timre >= (duration / 2)
- 只保留差异较大的考试。
✅ 第五步:输出并排序
select exam_id, duration, release_time
order by exam_id desc