题解 | # 每篇文章同一时刻最大在看人数#

每篇文章同一时刻最大在看人数

http://www.nowcoder.com/practice/fe24c93008b84e9592b35faa15755e48


一、知识点汇总与拓展

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
;

SQL解题集 文章被收录于专栏

这是牛客SQL相关的解题集

全部评论
请问一下为啥一定要是UNION ALL呢,我用UNION会出错?哪怕文章id和时间一致,uv也不一样啊?为什么结果会自动过滤掉一个?
2 回复 分享
发布于 2022-08-07 20:57
太清晰了
2 回复 分享
发布于 2022-05-27 09:44
太强啦!!!!!
1 回复 分享
发布于 2023-05-09 22:22 上海
SUM(uv)OVER(PARTITION BY artical_id ORDER BY in_time,uv DESC) 请问为什么要desc呀,desc只针对uv嘛
1 回复 分享
发布于 2022-09-01 18:23 北京
给您打call!
1 回复 分享
发布于 2022-06-01 17:51
🐂
点赞 回复 分享
发布于 2025-10-10 10:47 河南
点赞 回复 分享
发布于 2025-09-06 11:36 上海
hahha 在160 你说过同样的话
点赞 回复 分享
发布于 2024-03-17 19:21 湖北
考虑到同一时刻闪退情况的话是不是在窗口函数累加完,还需要对该表按ARTICLE_ID和时间戳进行用SUM聚合一下呢
点赞 回复 分享
发布于 2024-01-07 11:39 江苏
好厉害,我的神!!! 发现个小笔误,知识点拓展部分rows between 1 following 3 following #当前行的后1——>后3(共3行)这句代码忘记写and了好像 如果我没搞错的话
点赞 回复 分享
发布于 2023-11-21 17:43 加拿大
miaowa,怎么可以这么帅!!!!!
点赞 回复 分享
发布于 2023-05-18 11:22 河北
请问怎么能看到每一步运行的结果呀
点赞 回复 分享
发布于 2023-04-06 22:00 上海
统计时候,先进场后出场~
点赞 回复 分享
发布于 2022-09-01 18:26 北京
怎么理解同一时刻,我认为同一时刻不应该是一个固定的时间内吗
点赞 回复 分享
发布于 2022-06-19 10:34
你好,想请问一下,如果直接max(SUM(uv)OVER(PARTITION BY artical_id ORDER BY in_time,uv DESC))的话为什么不行呢
点赞 回复 分享
发布于 2022-06-17 16:57
强,厉害,棒棒哒,是真的牛批!
点赞 回复 分享
发布于 2022-06-07 11:43

相关推荐

评论
152
20
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务