SQL解决最多同时在线人数问题(同时视频观看人数,同时浏览人数,同时等车人数)
内容目录
今天拿到一个需求,要统计不同时间段的视频同时观看人数,举个例子,比如某个视频,video_id为9432870,统计出这个视频在10:00 - 12:00 同时观看人数最多为201人,12:00 - 14:00 同时观看人数最多为100人。
这个需求我刚接到的时候是很蒙圈的,不知道该怎么下手,我脑子第一反应就是,取并集?但是也不知道怎么取啊。问了公司的大佬,他告诉我让我想象成一个瞬时问题,就是求得某个时间点的同时在线人数,我恍然大悟,这个思路太妙了。
怎么理解呢,就是可以类比做坐公交车,现在是要统计最多在公交车上的人数,那我们应该怎么统计?要售票员每时每刻一遍一遍的数人数吗?这样肯定是不合理的,售票员一般都是在到站之后,会数人数,然后和票数确定一下是否一致。那么我们把这个思路用到这个需求上,其实我们也只需要在有人点击视频或者有人退出视频的时候计算即可。
一、要解决的问题
- 在什么时候去统计人数,用什么方式统计
- 按照什么方式去计算在线人数
二、如何解决
-
是么时候统计人数
我们可以把观看视频看作是一个业务过程,分析什么动作会产生人数增减,就像是公交车上的人数什么时候会变化。当视频有个人进来,我们就可以看作是增加了一人,就是有一个start_time,有人观看离开了,就看做是少了一人,就是产生end_time,那么这两个动作就是我们要做统计人数的时间。我们可以把增加一个人记作+1,减少一个人记作-1
select video_id ,start_time check_time ,1 as cnt from video_id where start_time is not null union all select video_id ,end_time check_time ,-1 as cnt from video_id where end_time is not null;
-
按照什么方式统计在线人数
我们统计在线人数是按照video_id 和 时间段,其实这里的检测范围也可以换做天,比如是天,我们可以将check_time转为天,然后按照video,check_time开窗,然后得到sum(cnt)的最大值
select video_id ,check_time ,max(online_cnt) from ( select video_id ,date(check_time) check_time ,sum(cnt) over(partition by video_id, date(check_time) order by check_time) online_cnt from t1 ) t2 group by city, check_time
三、扩展
其实同时在线问题,同时浏览问题,同时等车问题等,这些都可以采用这种方式,只不过我们要根据业务过程产生的动作判断什么情况会造成人员增减,把时间段的同时在线问题转变为时间点的同时在线问题,巧妙的解决问题。之所以是时间段能转变为时间点,是因为除了这些时间点之外,不会再有其他的改变人数的动作。具体如下图: