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

第二快/慢用时之差大于试卷时长一半的试卷

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表做连接

全部评论

相关推荐

评论
点赞
1
分享

创作者周榜

更多
牛客网
牛客企业服务