列表

详情


SQL189. 牛客直播各科目同时在线人数

描述

牛客某页面推出了数据分析系列直播课程介绍。用户可以选择报名任意一场或多场直播课。
已知课程表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

示例1

输入:

drop table if exists course_tb;
CREATE TABLE course_tb(
course_id int(10) NOT NULL, 
course_name char(10) NOT NULL,
course_datetime char(30) NOT NULL);
INSERT INTO course_tb VALUES(1, 'Python', '2021-12-1 19:00-21:00');
INSERT INTO course_tb VALUES(2, 'SQL', '2021-12-2 19:00-21:00');
INSERT INTO course_tb VALUES(3, 'R', '2021-12-3 19:00-21:00');

drop table if exists attend_tb;
CREATE TABLE attend_tb(
user_id int(10) NOT NULL, 
course_id int(10) NOT NULL,
in_datetime datetime NOT NULL,
out_datetime datetime NOT NULL
);
INSERT INTO attend_tb VALUES(100, 1, '2021-12-1 19:00:00', '2021-12-1 19:28:00');
INSERT INTO attend_tb VALUES(100, 1, '2021-12-1 19:30:00', '2021-12-1 19:53:00');
INSERT INTO attend_tb VALUES(101, 1, '2021-12-1 19:00:00', '2021-12-1 20:55:00');
INSERT INTO attend_tb VALUES(102, 1, '2021-12-1 19:00:00', '2021-12-1 19:05:00');
INSERT INTO attend_tb VALUES(104, 1, '2021-12-1 19:00:00', '2021-12-1 20:59:00');
INSERT INTO attend_tb VALUES(101, 2, '2021-12-2 19:05:00', '2021-12-2 20:58:00');
INSERT INTO attend_tb VALUES(102, 2, '2021-12-2 18:55:00', '2021-12-2 21:00:00');
INSERT INTO attend_tb VALUES(104, 2, '2021-12-2 18:57:00', '2021-12-2 20:56:00');
INSERT INTO attend_tb VALUES(107, 2, '2021-12-2 19:10:00', '2021-12-2 19:18:00');
INSERT INTO attend_tb VALUES(100, 3, '2021-12-3 19:01:00', '2021-12-3 21:00:00');
INSERT INTO attend_tb VALUES(102, 3, '2021-12-3 18:58:00', '2021-12-3 19:05:00');
INSERT INTO attend_tb VALUES(108, 3, '2021-12-3 19:01:00', '2021-12-3 19:56:00');

输出:

1|Python|4
2|SQL|4
3|R|3

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

Mysql 解法, 执行用时: 36ms, 内存消耗: 6384KB, 提交时间: 2022-01-01

select ct.course_id,ct.course_name,bt.max_num
from course_tb ct
join(
select course_id,max(at_num) as max_num
from(
select*, sum(num)over(partition by course_id order by course_id,at_time) as at_num
from(
select user_id,course_id,time(in_datetime) as at_time, 1 num 
from attend_tb 
union all
select user_id,course_id,time(out_datetime) as at_time, -1 num 
from attend_tb 
order by course_id,at_time
) a
) b
group by course_id
) bt
on ct.course_id=bt.course_id

Mysql 解法, 执行用时: 36ms, 内存消耗: 6476KB, 提交时间: 2022-01-22

select
e.course_id,
e.course_name,
max(cnt) max_num
from
(SELECT
d.course_id,
d.course_name,
sum(zaixian) over (partition by course_id order by dt,zaixian desc) cnt
from
(select
a.course_id,
a.course_name,
in_datetime dt,
1 zaixian
from
course_tb a left join attend_tb b on a.course_id=b.course_id
 
union all
select
a.course_id,
a.course_name ,  
out_datetime dt,
-1 zaixian
from
course_tb a left join attend_tb b on a.course_id=b.course_id
)  d) e
group by 1,2
order by 1

Mysql 解法, 执行用时: 37ms, 内存消耗: 6380KB, 提交时间: 2022-01-24

with t1 as (
    select
        user_id,
        course_id,
        in_datetime as on_time,
        1 as diff -- 进入直播间
    from attend_tb
    union
    select
        user_id,
        course_id,
        out_datetime as on_time,
        -1 as diff -- 离开直播间
    from attend_tb
),
t2 as (
    select
        course_id,
        sum(diff) over (partition by course_id order by on_time, diff desc) as num
    from t1
),
t3 as (
    select distinct
        course_id, num,
        max(num) over (partition by course_id) as max_num
    from t2
)
select
    t3.course_id, c.course_name, t3.max_num
from t3
left join course_tb c on c.course_id = t3.course_id
where num = max_num
order by course_id asc;

Mysql 解法, 执行用时: 37ms, 内存消耗: 6384KB, 提交时间: 2022-01-25

select course_id, course_name,
max(ranks) as max_num
from
(
    select 
    a.course_id, course_name, 
    sum(flag) over(partition by a.course_id, course_name order by times, flag desc) as ranks
    from
    (
        select course_id, in_datetime as times, 1 as flag
        from attend_tb
        union all 
        select course_id, out_datetime as times, -1 as flag
        from attend_tb
    ) as a
    left join course_tb as b
    on a.course_id = b.course_id
) as c
group by course_id, course_name

Mysql 解法, 执行用时: 37ms, 内存消耗: 6416KB, 提交时间: 2021-12-19

-- 2021年12月18日

with attend_detail as  (
    select 
    course_id, active_time, sum(cnt) as cnt
    from (
        select course_id, in_datetime as active_time, 1 as cnt from attend_tb 
        union all
        select course_id, out_datetime as active_time, -1 as cnt from attend_tb 
    ) t
    group by course_id, active_time
)

select 
  t2.course_id as course_id
, c.course_name as course_name 
, t2.max_num as max_num
from (
    select 
    course_id, max(online_num) as max_num
    from (
        select 
          a1.course_id as course_id 
        , a1.active_time as active_time
        , ifnull(sum(a2.cnt),0) as online_num
        from attend_detail a1 
        left outer join attend_detail a2 
            on a1.course_id = a2.course_id 
            and a1.active_time >= a2.active_time 
        -- where a1.cnt = 1 -- 最大人数必然最早发生在进入的时间
        group by a1.course_id, a1.active_time
    ) t1
    group by course_id
) t2
inner join course_tb c 
    on t2.course_id = c.course_id 
order by course_id 
;