一、问题拆解:①活跃天数界定,进出时间跨天当作两天活跃;②判断是否新增用户;③判断是否次日留存。 二、解决步骤: ①活跃天数界定:因为跨天也算活跃,所以把out_time通过union跟in_time联立到一列,记为活跃日期active_day; ②新增用户if_new:该uid所有活跃日期里最小的一天,将该日期编号1否则为0,用窗口函数min配合if进行编号; ③次日留存if_lastday:即当日活跃,当日+1也活跃即为次日留存,将该日期编号1否则为0,则用窗口函数lead配合if进行编号; ④筛选与计算: 筛选条件:(1)2021年11月(时间筛选放在计算层,在计算之前的子查询里筛会导致11月以前的数据缺失,这样11月的老 用户会误认为新用户);(2)新增用户数据,即新增用户列的编号为1。 计算结果:根据日期分组,计算(if_new、if_lastday同时为1的人数)/(if_new为1的人数)即可。 select active_day as dt, round(sum(if(if_new=1 and if_lastday=1,1,0))/sum(if_new),2) as uv_left_rate from( #用窗口函数+if对是否新增、是否次日留存进行编号,是为1、不是为0 select uid, active_day, if(min(active_day)over(partition by uid)=active_day,1,0) as if_new, if(lead(active_day,1)over(partition by uid order by active_day)=date_add(active_day,interval 1 day),1,0) as if_lastday from( #in和out联立,均当作活跃日期 select uid, date(in_time) as active_day from tb_user_log union all select uid, date(out_time) as active_day from tb_user_log ) as tb1 group by uid, active_day ) as tb2 where if_new=1 and date_format(active_day,'%Y%m')='202111' group by dt order by dt