SQL166. 每天的日活数及新用户占比
描述
用户行为日志表tb_user_log
id | uid | artical_id | in_time | out_time | sign_cin |
1 | 101 | 9001 | 2021-10-31 10:00:00 | 2021-10-31 10:00:09 | 0 |
2 | 102 | 9001 | 2021-10-31 10:00:00 | 2021-10-31 10:00:09 | 0 |
3 | 101 | 0 | 2021-11-01 10:00:00 | 2021-11-01 10:00:42 | 1 |
4 | 102 | 9001 | 2021-11-01 10:00:00 | 2021-11-01 10:00:09 | 0 |
5 | 108 | 9001 | 2021-11-01 10:00:01 | 2021-11-01 10:00:50 | 0 |
6 | 108 | 9001 | 2021-11-02 10:00:01 | 2021-11-02 10:00:50 | 0 |
7 | 104 | 9001 | 2021-11-02 10:00:28 | 2021-11-02 10:00:50 | 0 |
8 | 106 | 9001 | 2021-11-02 10:00:28 | 2021-11-02 10:00:50 | 0 |
9 | 108 | 9001 | 2021-11-03 10:00:01 | 2021-11-03 10:00:50 | 0 |
10 | 109 | 9002 | 2021-11-03 11:00:55 | 2021-11-03 11:00:59 | 0 |
11 | 104 | 9003 | 2021-11-03 11:00:45 | 2021-11-03 11:00:55 | 0 |
12 | 105 | 9003 | 2021-11-03 11:00:53 | 2021-11-03 11:00:59 | 0 |
13 | 106 | 9003 | 2021-11-03 11:00:45 | 2021-11-03 11:00:55 | 0 |
dt | dau | uv_new_ratio |
2021-10-30 | 2 | 1.00 |
2021-11-01 | 3 | 0.33 |
2021-11-02 | 3 | 0.67 |
2021-11-03 | 5 | 0.40 |
示例1
输入:
DROP TABLE IF EXISTS tb_user_log; CREATE TABLE tb_user_log ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID', uid INT NOT NULL COMMENT '用户ID', artical_id INT NOT NULL COMMENT '视频ID', in_time datetime COMMENT '进入时间', out_time datetime COMMENT '离开时间', sign_in TINYINT DEFAULT 0 COMMENT '是否签到' ) CHARACTER SET utf8 COLLATE utf8_bin; INSERT INTO tb_user_log(uid, artical_id, in_time, out_time, sign_in) VALUES (101, 9001, '2021-10-31 10:00:00', '2021-10-31 10:00:09', 0), (102, 9001, '2021-10-31 10:00:00', '2021-10-31 10:00:09', 0), (101, 0, '2021-11-01 10:00:00', '2021-11-01 10:00:42', 1), (102, 9001, '2021-11-01 10:00:00', '2021-11-01 10:00:09', 0), (108, 9001, '2021-11-01 10:00:01', '2021-11-01 10:01:50', 0), (108, 9001, '2021-11-02 10:00:01', '2021-11-02 10:01:50', 0), (104, 9001, '2021-11-02 10:00:28', '2021-11-02 10:00:50', 0), (106, 9001, '2021-11-02 10:00:28', '2021-11-02 10:00:50', 0), (108, 9001, '2021-11-03 10:00:01', '2021-11-03 10:01:50', 0), (109, 9002, '2021-11-03 11:00:55', '2021-11-03 11:00:59', 0), (104, 9003, '2021-11-03 11:00:45', '2021-11-03 11:00:55', 0), (105, 9003, '2021-11-03 11:00:53', '2021-11-03 11:00:59', 0), (106, 9003, '2021-11-03 11:00:45', '2021-11-03 11:00:55', 0);
输出:
2021-10-31|2|1.00 2021-11-01|3|0.33 2021-11-02|3|0.67 2021-11-03|5|0.40
Mysql 解法, 执行用时: 36ms, 内存消耗: 6436KB, 提交时间: 2022-02-09
select dt, count(*) as dau, round(sum(new)/count(*), 2) as uv_new_ratio from ( select uid, dt, case when dt = first_dt then 1 else 0 end as new from (select uid, date(in_time) as dt from tb_user_log UNION select uid, date(out_time) as dt from tb_user_log) t1 left join (select uid, min(date(in_time)) as first_dt from tb_user_log group by uid) t2 using(uid) ) t group by dt order by dt
Mysql 解法, 执行用时: 36ms, 内存消耗: 6500KB, 提交时间: 2022-01-23
select dt ,count(distinct t1.uid) as dau ,round(count(distinct case when dt=new_date then t1.uid else null end )/count(distinct t1.uid),2) as uv_new_ratio FROM ( select uid ,date(in_time) as dt from tb_user_log union select uid ,date(out_time) as dt from tb_user_log group by uid ,dt )t1 left join ( select uid ,date(min(in_time)) as new_date from tb_user_log group by uid )t2 on t1.uid=t2.uid group by dt order by dt
Mysql 解法, 执行用时: 37ms, 内存消耗: 6372KB, 提交时间: 2022-01-22
select new_t.dt,dau_t.dau,round(new_t.new/dau_t.dau,2) as uv_new_ratio from (select a.dt,if(b.day is null,0,b.new) as new from (select distinct date(in_time) as dt from tb_user_log) as a left join (select date(new_day) as day,count(uid) as new FROM (select uid,min(in_time) as new_day from tb_user_log group by uid) as t group by day) as b on a.dt=b.day) as new_t JOIN (select p.day,if(p.dau>q.dau,p.dau,q.dau) as dau from (select date(in_time) as day,count(distinct uid) as dau from tb_user_log group by day) as p JOIN (select date(out_time) as day,count(distinct uid) as dau from tb_user_log group by day) as q on p.day=q.day) as dau_t on new_t.dt=dau_t.day order by new_t.dt
Mysql 解法, 执行用时: 37ms, 内存消耗: 6392KB, 提交时间: 2022-01-06
select dt, count(uid)as dau, round(sum(if(times=1,1,0))/count(uid),2)as nv_new_ratio from ( select *, count(*) over (partition by uid order by dt)as times from ( select uid, date(in_time) as dt from tb_user_log union select uid, date(out_time) as dt from tb_user_log ) t1 ) t2 group by dt order by dt
Mysql 解法, 执行用时: 37ms, 内存消耗: 6392KB, 提交时间: 2021-12-27
with t1 as ( select uid,min(date(in_time)) min_date from tb_user_log group by uid), t2 as( select uid,date(in_time) dt from tb_user_log union select uid,date(out_time) dt from tb_user_log) select dt,count(*),round(count(min_date)/count(*),2) from( SELECT t2.uid,dt,min_date from t2 left join t1 on t2.uid=t1.uid and t2.dt=t1.min_date) t3 group by dt order by dt