一、确定总体问题
- 每个日期 新用户 的次日留存 率 -- 关键问题
 - 结果保留小数点后面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)  |     
如何写制约条件?
  
 

京公网安备 11010502036488号