牛客SQL34: 牛客直播各科目同时在线人数(最大值问题)
一、描述
牛客某页面推出了数据分析系列直播课程介绍。用户可以选择报名任意一场或多场直播课。
已知课程表course_tb如下(其中course_id代表课程编号,course_name表示课程名称,course_datetime代表上课时间):
course_id |
course_name |
course_datetime |
1 |
Python |
2021-12-1 19:00-21:00 |
2 |
SQL |
2021-12-2 19:00-21:00 |
3 |
R |
2021-12-3 19:00-21:00 |
上课情况表attend_tb如下(其中user_id表示用户编号、course_id代表课程编号、in_datetime表示进入直播间的时间、out_datetime表示离开直播间的时间):
user_id |
course_id |
in_datetime |
out_datetime |
100 |
1 |
2021-12-01 19:00:00 |
2021-12-01 19:28:00 |
100 |
1 |
2021-12-01 19:30:00 |
2021-12-01 19:53:00 |
101 |
1 |
2021-12-01 19:00:00 |
2021-12-01 20:55:00 |
102 |
1 |
2021-12-01 19:00:00 |
2021-12-01 19:05:00 |
104 |
1 |
2021-12-01 19:00:00 |
2021-12-01 20:59:00 |
101 |
2 |
2021-12-02 19:05:00 |
2021-12-02 20:58:00 |
102 |
2 |
2021-12-02 18:55:00 |
2021-12-02 21:00:00 |
104 |
2 |
2021-12-02 18:57:00 |
2021-12-02 20:56:00 |
107 |
2 |
2021-12-02 19:10:00 |
2021-12-02 19:18:00 |
100 |
3 |
2021-12-03 19:01:00 |
2021-12-03 21:00:00 |
102 |
3 |
2021-12-03 18:58:00 |
2021-12-03 19:05:00 |
108 |
3 |
2021-12-03 19:01:00 |
2021-12-03 19:56:00 |
请你统计每个科目最大同时在线人数(按course_id排序),以上数据的输出结果如下:
course_id |
course_name |
max_num |
1 |
Python |
4 |
2 |
SQL |
4 |
3 |
R |
3 |
二、思路解析
这其实是一个瞬时最大值问题,解题详情见sql解决连续问题
这类题的解析步骤可以分为以下
- 找到数量变化的时间点,比如进入直播间和退出直播间等
- 对数量变化做出相应的+1和-1操作
- 按照题目规定对某个字段分组排序开窗求和,获取最大值
三、代码
-- 1. 处理人数增减
with t1 as (
select tt.course_id
,course_name
,in_datetime event_time
,1 as cnt
from attend_tb tt
left join course_tb
using(course_id)
union all
select tt.course_id
,course_name
,out_datetime event_time
,-1 as cnt
from attend_tb tt
left join course_tb
using(course_id)
),
-- 2. 按照course_id分组
t2 as (
select course_id
,course_name
,event_time
,sum(cnt)
over(partition by course_id order by event_time) online_cnt
from t1
)
select course_id
,course_name
,max(online_cnt) max_num
from t2
group by course_id, course_name
order by course_id
四、问题思考
sum(column3) over(partition by column1 order by column2)
和
sum(column3) over(partition by column1 order by column2 rows between unbounded preceding and current row)
上述两者的区别
准备数据,向表里增加一些测试数据,不用太多
-- 创建表
create table user_tb(
user_id string,
score int
);
-- 插入数据
insert into user_tb
values('1001',1),
('1001',10),
('1001',100);
测试1:
select user_id
,score
,sum(score)
over(partition by user_id order by score)
from user_tb;
测试2:
select user_id
,score
,sum(score)
over(partition by user_id order by score rows between unbounded preceding and current row) from user_tb;
这里可以看出,这两个用法的结果其实是一样的,只是中间的计算逻辑不同