一、知识点汇总与拓展

1)学到了一个非常实用的计算实时在线UV的方法,进入定义为1,离开定义为-1,并对时间进行正序排序,最后算累加实时在线UV。
2)另一个知识点就是窗口函数啦,sum()over(order by 字段1):按照字段1的排序依次进行累加,这个其实是开窗函数框架限定的缩写应用。
    完整的写法是sum()over(order by 字段名 rows between unbounded preceding and current row)

继续复习滑动窗口函数

开窗函数的框架限定算数我的知识盲区吧,这里正好用到了,顺便完成了一项SQL的查缺补漏。
  • rows n perceding:从当前行到前n行(一共n+1行)
  • rang/rows between 边界规则1 and 边界规则2:rang表示按照值的范围进行定义框架,rows表示按照行的范围进行定义框架
rows between 2perceding and 2following #当前行往前2行+当前行+当前行往后2行(一共5行)
rows between 1 following 3 following #当前行的后1——>后3(共3行)
rows between unbounded preceding and current row #从第一行到当前行

二、解题步骤

  • 这个题目的难点在于计算同时在线UV。我思考了非常久,并没有理解进入先加离开后减是什么意思。看了几个人的答案,大概理解了这个逻辑:就像直播间一样,时时刻刻有人进,时时刻刻有人出,进来的人加上1,出去的人减掉1,这样想就想通了。
  • 有一个坑点是,在累加的时候,要对uv进行排序,以用户进入的uv为优先级,在现实场景中,这个点是可以理解的(比如同一秒,用户进入就闪退呢,应该优先计算他的进入数据),但在写sql的时候我忽略了,以至于我运行了好多次都报错。

1)统计每篇文章同一时刻最大在看人数
按照题目提示,把进来算作1,离开算作-1。用sum()over(order by time)来进行累加统计实时在线。取实时在线的最大值即为同一时刻文章再看最大值。

2)如果同一时刻有进入也有离开时,先记录用户数增加再记录减少
  • 进入uv=1,离开uv=-1
SELECT uid,artical_id,in_time,1 AS uv FROM tb_user_log
UNION ALL
SELECT uid,artical_id,out_time,-1 AS uv FROM tb_user_log

  • 累加uv,计算用户最大同时在线数据
SELECT artical_id,in_time,uv,
    SUM(uv)OVER(PARTITION BY artical_id ORDER BY in_time,uv DESC) uv_cnt
    # 先计算用户进入的uv,因为会存在用户同一秒进出的情况,这时肯定是优先统计用户进场的情况的。
FROM (SELECT uid,artical_id,in_time,1 AS uv FROM tb_user_log
    UNION ALL
    SELECT uid,artical_id,out_time,-1 AS uv FROM tb_user_log) as uv_table
WHERE artical_id<>0;#题目有说artical_id<>0

4)结果按最大人数降序。
取最大同时在线数,并按照max_uv 逆序排序。
WITH t1 AS 
(SELECT artical_id,in_time,
        SUM(uv)OVER(PARTITION BY artical_id ORDER BY in_time,uv DESC) uv_cnt
FROM (SELECT uid,artical_id,in_time,1 AS uv FROM tb_user_log
    UNION ALL
    SELECT uid,artical_id,out_time,-1 AS uv FROM tb_user_log) as uv_table
WHERE artical_id<>0
)
SELECT artical_id,MAX(uv_cnt) max_uv FROM t1
GROUP BY artical_id
ORDER BY max_uv DESC
;