题解 137 | #第二快/慢用时之差大于试卷时长一半的试#

【场景】:与某行数据的差

【分类】:专用窗口函数、嵌套子查询

分析思路

难点:

1.查询第二慢和第二快的(一个正序排名第二,一个倒序第二),nth_value(expr,n)可以取expr列第n行的数两者求差,另一种方法是排序之后向下平移一位再做差。

2.换算成秒来计算作答时间

(1)统计试卷每次作答的时间(秒)

​ [条件]:submit_time is not null

​ [使用]:timestampdiff(second,start_time,submit_time)

(2)查询第二慢和第二快的用时记录(一个正序排名第二,一个倒序第二)

​ [使用]:nth_value(second,2) over(partition by exam_id order by second);nth_value(second,2) over(partition by exam_id order by second desc)

(3)统计第二快和第二慢用时之差大于试卷时长的一半的试卷信息,按试卷ID降序排序

​ [条件]:where 第二快 - 第二慢 - duration*60/2 > 0(换算成秒)

最终结果

select 查询结果 [试卷类型; 用户ID;排名]
from 从哪张表中查询数据[嵌套from子查询]
where 查询条件 [每类试卷得分的前3名]

扩展

前往查看: MySQL 窗口函数

求解代码

方法一

with子句 + 使用nth_value()

with 
    temp as(
        #统计试卷每次作答的时间(秒)
        select
            a.exam_id,
            duration,
            timestampdiff(second,start_time,submit_time) as second
        from examination_info a,exam_record b
        where a.exam_id=b.exam_id
        and submit_time is not null
    ),
    temp1 as(
        #查询第二慢和第二快的用时记录(一个正序排名第二,一个倒序第二)
        select 
            exam_id,
            duration*60/2 as duration,
            second,
            nth_value(second,2) over(partition by exam_id order by second) as row_asc,
            nth_value(second,2) over(partition by exam_id order by second desc) as row_desc
        from temp
    )

#统计第二快和第二慢用时之差大于试卷时长的一半的试卷信息,按试卷ID降序排序
select distinct
    exam_id,
    duration,
    release_time
from examination_info
join temp1 using(exam_id)
where row_desc-row_asc - temp1.duration > 0
order by exam_id desc

方法二

with子句 + 使用row_number()和lag(exrp,number)

with 
    temp1 as(
        #统计试卷每次作答的时间(秒)
        select
            a.exam_id,
            a.duration,
            timestampdiff(second,start_time,submit_time) as second
        from examination_info a,exam_record b
        where a.exam_id=b.exam_id
        and submit_time is not null
    ),
    temp2 as(
        #统计每个试卷每次作答时间正序和倒序
        select
            exam_id,
            duration,
            second,
            row_number() over(partition by exam_id order by second) as row_asc,
            row_number() over(partition by exam_id order by second desc) as row_desc
        from temp1
    ),
    temp3 as(
        #正序=2为第二慢,倒序=2为第二快
        select 
            exam_id,
            duration,
            second
        from temp2
        where (row_asc = 2 or row_desc = 2)
    ),
    temp4 as (
        #按照试卷类型分组后再按照作答时间向下平移一位得到pre_second
        select 
            exam_id,
            duration*60/2 as duration,
            second,
            lag(second,1) over (partition by exam_id order by second desc) as pre_second
        from temp3
    )
#统计第二快和第二慢用时之差大于试卷时长的一半的试卷信息,按试卷ID降序排序
select
    a.exam_id,
    a.duration,
    release_time
from examination_info a
join temp4
using(exam_id)
where pre_second-second - temp4.duration > 0
order by exam_id desc

方法三

嵌套子查询 + join子查询 + nth_value()

#统计第二快和第二慢用时之差大于试卷时长的一半的试卷信息,按试卷ID降序排序
select distinct
    exam_id,
    a.duration,
    release_time
from examination_info a
join(
    #查询第二慢和第二快的用时记录(一个正序排名第二,一个倒序第二)
    select 
        exam_id,
        duration*60/2 as duration,
        second,
        nth_value(second,2) over(partition by exam_id order by second) as row_asc,
        nth_value(second,2) over(partition by exam_id order by second desc) as row_desc
    from(
        #统计试卷每次作答的时间(秒)
        select
            a.exam_id,
            duration,
            timestampdiff(second,start_time,submit_time) as second
        from examination_info a,exam_record b
        where a.exam_id=b.exam_id
        and submit_time is not null
    ) temp
) temp1 using(exam_id)
where row_desc-row_asc - temp1.duration > 0
order by exam_id desc
全部评论

相关推荐

挣K存W养DOG:他真的很中意你,为什么不回他
点赞 评论 收藏
分享
牛客963010790号:为什么还要收藏
点赞 评论 收藏
分享
1 1 评论
分享
牛客网
牛客企业服务