订阅更新

首日次日留存率:AVG 一个布尔值

SQL 实战 123 题 · 第 17 题 中等 约 2 分钟读完

LeetCode 550 · 次日留存、LEFT JOIN、条件求平均

本文目录
  1. 面试怎么回答
  2. 题意
  3. 表结构
  4. 思路
  5. 参考解法
  6. 易错点

面试怎么回答

这是次日留存。先按玩家求首登日,再 LEFT JOIN 活动表找 DATEDIFF = 1 的记录,用 AVG(a.event_date IS NOT NULL) 直接得到留存比例。LEFT JOIN 保证分母是全部玩家,布尔值求平均等于命中数除以总数。

先把这段讲顺;面试官追问时,再展开下面的原理和细节。

详细讲解

题意

计算「首次登录后第二天又登录了」的玩家,占全部玩家的比例,保留两位小数。

表结构

  • Activity:player_id、device_id、event_date、games_played;(player_id, event_date) 为主键

思路

先求每个玩家的首次登录日期,再用 LEFT JOIN 去找「首日 + 1 天」的登录记录:找得到的玩家留存了,找不到的那一列为 NULL。对「是否找得到」这个布尔值求平均,就是留存玩家数 / 总玩家数,一步出比例。

参考解法

select round(avg(a.event_date is not null), 2) fraction
from 
    (select player_id, min(event_date) as login
    from activity
    group by player_id) p 
left join activity a 
on p.player_id=a.player_id and datediff(a.event_date, p.login)=1

易错点

  • 用 INNER JOIN 会把没留存的玩家丢掉,分母变小。
  • 题目要的是首日的次日,不是任意相邻两天都登录。
刷题进度保存在当前浏览器