题解 | #第二快/慢用时之差大于试卷时长一半的试卷#
第二快/慢用时之差大于试卷时长一半的试卷
https://www.nowcoder.com/practice/b1e2864271c14b63b0df9fc08b559166
看了高赞回答,自己记录一下解题过程和高赞回答的解题过程便于复习
自己的过程
函数
1)排序窗口函数
- rank() over() 1 2 2 4 4 6 (计数排名,跳过相同的几个,eg.没有3没有5)
- row_number() over() 1 2 3 4 5 6 (赋予唯一排名)
- dense_rank() over() 1 2 2 3 3 4 (不跳过排名,可以理解为对类别进行计数)
2)时间差函数
timestampdiff(unit, begin, end)
- unit :单位
- begin : 一般是小的时间
- end : 一般是大的时间
思路分析
1) 用开窗函数按照exam_id分区,按照用时timestampdiff(minute, start_time, submit_time)正序,并筛选出第二快的数据:ranking=2的数据【注意筛选需要另外再select】,这个表为t2表
select
*
from
(
select
uid,
exam_id,
timestampdiff(minute, start_time, submit_time) as answer_time,
row_number() over(
partition by exam_id
order by
timestampdiff(minute, start_time, submit_time) desc
) as time_rank
from
exam_record
where
submit_time is not null
) t1
where
time_rank = 2

2) 用开窗函数按照exam_id分区,按照用时timestampdiff(minute, start_time, submit_time)倒序,并筛选出第二蛮的数据:ranking=2的数据【这张表为t4】
select
*
from
(
select
uid,
exam_id,
timestampdiff(minute, start_time, submit_time) as answer_time,
row_number() over(
partition by exam_id
order by
timestampdiff(minute, start_time, submit_time)
) as time_rank
from
exam_record
where
submit_time is not null
) t3
where
time_rank = 2

3) 按exam_id连接这两张表以及examination_info, 需要duration和release_time字段,按条件筛选即可
select
t2.exam_id,
info.duration,
info.release_time
from
(
select
*
from
(
select
uid,
exam_id,
timestampdiff(minute, start_time, submit_time) as answer_time,
row_number() over(
partition by exam_id
order by
timestampdiff(minute, start_time, submit_time) desc
) as time_rank
from
exam_record
where
submit_time is not null
) t1
where
time_rank = 2
) t2
高赞过程
主要是将第二快和第二慢的数据放在一张表中,然后用case when then else end将第二快和第二慢的时间分出来聚合,可以减少连接表的数量
1) 将第二快和第二慢的数据放在一张表
SELECT
uid,
exam_id,
TIMESTAMPDIFF(MINUTE, start_time, submit_time) AS answer_time,
ROW_NUMBER() OVER(
PARTITION BY exam_id
ORDER BY
TIMESTAMPDIFF(MINUTE, start_time, submit_time)
) ascrank,
ROW_NUMBER() OVER(
PARTITION BY exam_id
ORDER BY
TIMESTAMPDIFF(MINUTE, start_time, submit_time) DESC
) descrank
FROM
exam_record
WHERE
submit_time IS NOT NULL

2)计算第二快和第二慢的时间差值
SELECT
exam_id,
SUM(
CASE
WHEN ascrank = 2 THEN - answer_time
WHEN descrank = 2 THEN answer_time
ELSE 0
END
) AS answer_time_diff
FROM
(
SELECT
uid,
exam_id,
TIMESTAMPDIFF(MINUTE, start_time, submit_time) AS answer_time,
ROW_NUMBER() OVER(
PARTITION BY exam_id
ORDER BY
TIMESTAMPDIFF(MINUTE, start_time, submit_time)
) ascrank,
ROW_NUMBER() OVER(
PARTITION BY exam_id
ORDER BY
TIMESTAMPDIFF(MINUTE, start_time, submit_time) DESC
) descrank
FROM
exam_record
WHERE
submit_time IS NOT NULL
) t
GROUP BY
exam_id

3)和examination_info表做连接

