法一:
SELECT ROUND(COUNT(t2.user_id)/ COUNT(t1.user_id),3) p FROM
(SELECT user_id, MIN(date) date FROM login GROUP BY user_id) t1
LEFT JOIN
(SELECT DISTINCT user_id, DATE_SUB(date, INTERVAL 1 DAY) AS newdate
FROM login) t2
ON t1.user_id=t2.user_id AND t1.date=t2.newdate;
和这题很像https://blog.nowcoder.net/n/1eb2c32badec4f1cad27c7033aa2a742, 区别在于这里是求新用户的次日留存率,那里是求所有用户的次日留存率。
PS:就本题而言,登录表不会有user_id,date 重复的,去掉DISTINCT 也行。
法二,只要一个select然后加限定条件(从讨论区高赞处学习到):
SELECT ROUND(COUNT(user_id)/(SELECT COUNT(DISTINCT user_id) FROM login),3)
FROM login
WHERE (user_id,date) IN (SELECT user_id,DATE_ADD(MIN(date),INTERVAL 1 DAY)
FROM login GROUP BY user_id);