牛客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;
这里可以看出,这两个用法的结果其实是一样的,只是中间的计算逻辑不同