一、确定总体问题
- 每个日期 新用户 的次日留存 率 -- 关键问题
- 结果保留小数点后面3位数(3位之后的四舍五入) --次要问题
- 并且查询结果按照日期升序排序 -- 次要问题
二、分析关键问题(约束条件)
- 每个日期的新用户数--分母
- 每个日期的新用户次日留存--分子
- 求比率 (/)
分析:
1.究竟将约束条件放在哪里?用什么关键字好?下面提供两个角度
【角度① 分析关系】:既然求比率,就要分别求分子分母,他们两属于包含关系,所以可以根据‘漏斗模型’,将约束条件放在from left join中描述(下面的方法一详细讲述)
2.用什么来求数值?count还是sum?
若用角度①,则要用count而不能用sum来聚合符合条件的数量,因为条件写在from left join中并没有对其赋值若用角度②,则count和sum都可以,因为用的case when 中有赋值,而且仅仅是计数,所以两者都能用。角度②具体如下:
COUNT(CASE WHEN THEN 1 ELSE NULL END)-- 跳过NULL值
SUM(CASE WHEN THEN 1 ELSE 0或NULL END)-- 跳过NULL值
三、搭框架
【方法一的详细SQL】
select t0.date, ifnull(round(count(distinct t2.user_id)/(count(t1.user_id)),3),0) from ( select date from login group by date ) t0 left join ( select user_id,min(date) as date from login group by user_id )t1 on t0.date=t1.date left join login as t2 on t1.user_id=t2.user_id and datediff(t2.date,t1.date)=1 group by t0.date
【方法二的详细SQL】
SELECT date,IFNULL(ROUND(SUM(CASE WHEN (user_id,date) IN (SELECT user_id,DATE_ADD(date,INTERVAL -1 DAY) FROM login) AND (user_id,date) IN (SELECT user_id,MIN(date) FROM login GROUP BY user_id) THEN 1 ELSE 0 END)/ SUM(CASE WHEN (user_id,date) IN (SELECT user_id,MIN(date) FROM login GROUP BY user_id) THEN 1 ELSE 0 END),3),0) AS p FROM login GROUP BY date ORDER BY date;
两种框架的比较
共性:
- ifnull(考虑分母为0,即当天没有新用户的情况)--求比率问题必须考虑的特殊情况
- round(四舍五入保留三位小数)--数值型格式要求
- group by 和order by(按date分组和升序)--结果展示要求
异性:
一、约束条件放置位置不同 --(决定运用何种框架)
【方法一(间接法)】放在from left join中。类比拿来主义,因为已经在from中写好约束条件,所以直接拿from表格中的某些字段用于count的字段粗框架:
select date,IFNULL(ROUND(count()/count(),3, from (select 去重的日期表) left join on (select 新用户的首次登陆日期表 ) left join on (select 新用户的次日登录日期表 ) group by ORDER BY
该框架类比漏斗模型,左边最宽,向右逐次缩窄,需满足的条件也越来越严苛
【方法二(直接法)】放在比率(分子分母)的case when中
粗框架:
SELECT date,IFNULL(ROUND(SUM(CASE WHEN ...) / (SUM(CASE WHEN ...),3),0) FROM login GROUP BY date ORDER BY date;
二、约束条件的写法对比
条件 / 框架 | 条件写在from left join里 | 条件写在case when里 |
每日 新用户数 | ...left join (select user_id,min(date) as date from login group by user_id )t1 on t0.date=t1.date | CASE WHEN (user_id,date) IN (SELECT user_id,MIN(date) FROM login GROUP BY user_id) THEN 1 ELSE 0 END |
每日 新用户 次日留存数 | ...left join login as t2 on t1.user_id=t2.user_id and datediff(t2.date,t1.date)=1 | CASE WHEN (user_id,date) IN(SELECT user_id,DATE_ADD(date,INTERVAL -1 DAY) FROM login) AND (user_id,date) IN (SELECT user_id,MIN(date) FROM login GROUP BY user_id) THEN 1 ELSE 0 END) |
如何写制约条件?