描述
现有试卷信息表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