select 
a.date
,round(ifnull(b.first_next_num/a.first_num, 0), 3) p #当天首次登录并且次日也登录的人数/首次登录的人数即为当天留存率
from ( # 新用户表
        select distinct date # 该查询主要目的是:找到每个日期的新用户数
        ,sum(case when (user_id, date) in (select user_id, min(date) from login group by 1) then 1 else 0 end) first_num # 首次登录日期总人数
        from login l
        group by 1
     ) a
left join ( # 次日留存用户表
                select count(user_id) first_next_num # 该查询主要目的是:找到首次登录并且次日又登录的用户数,也就是次日留存用户数
                ,date_add(date, interval -1 day) date2 # 首次登录日期
                from login
                where (user_id, date) in ( # 找到首次登录同时次日也登录的用户id和次日登录日期
                                            select
                                            user_id
                                            ,date_add(min(date), interval 1 day)
                                            from login
                                            group by 1
                                        )
                group by date2
            ) b
on a.date = b.date2
order by a.date;