知识点
- 根据题目想要的表格的形状首先按照日期排列,知道每个日期有哪些新用户,然后第二天该用户登录信息没有也要出现null值因此该题使用左连接
- 第一步日期排列代码如下
select date
from login
group by date
- 该日期有哪些新用户代码如下,即使出现同一人当天多次登录的情况这样写也不会出现重复。日期没有新人后面就是null值
select user_id, min(date) as date
from login
group by user_id
- 然后再左连接login表,连接条件为用户id同时使用datediff(date1,date2) 返回起始时间 date1 和结束时间 date2 之间的天数为1。若没有符合条件的连接的表date就是null值。
- 由于出现null值可以直接使用ifnull。如果不是 NULL,则返回第一个参数。 否则,IFNULL 函数返回第二个参数。该题出现null值就是0
- 计算留存率,有可能出现第二天登录多次的情况所以计数时使用distinct。
代码
select d1.date,
ifnull (round(
count(distinct l.user_id)/(count(distinct d2.user_id)), 3) ,0) as p
from(
select date
from login
group by date) as d1
left join
(
select user_id, min(date) as date
from login
group by user_id) as d2
on d1.date = d2.date
left join login as l
on d2.user_id = l.user_id
and datediff(l.date, d2.date) = 1
group by d1.date
补充
- on条件是在生成临时表时使用的条件,它不管on中的条件是否为真,都会返回左边表中的记录。
- where条件是在临时表生成好后,再对临时表进行过滤的条件。这时已经没有left join的含义(必须返回左边表的记录)了,条件不为真的就全部过滤掉,on后的条件用来生成左右表关联的临时表,where后的条件对临时表中的记录进行过滤。