近 30 天人均会话数
LeetCode 1142 · 比率指标、去重计数、空结果处理
面试怎么回答
在近 30 天的数据上,COUNT(DISTINCT session_id) / COUNT(DISTINCT user_id),ROUND 两位,IFNULL 处理没有数据的情况。前提是一个会话只属于一个用户,否则要先按用户计数再求平均。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
题意
同一张活动表,计算截至 2019-07-27 的 30 天内,每个活跃用户平均有多少个会话,保留两位小数;没有活跃用户时返回 0。
表结构
- Activity:user_id、session_id、activity_date、activity_type;每个会话只属于一个用户
思路
人均会话数 = 不同会话数 / 不同用户数。因为每个会话只属于一个用户,可以直接在全量上用两个 COUNT(DISTINCT) 相除;没有数据时除法得到 NULL,用 IFNULL 返回 0。日期范围的注意点同上一题。
参考解法
SELECT IFNULL(ROUND(COUNT(DISTINCT session_id) / COUNT(DISTINCT user_id), 2), 0) AS average_sessions_per_user
from Activity
where activity_date > date_add('2019-07-27',INTERVAL -1 MONTH)
易错点
- 用 COUNT(*) 会把同一会话的多条行为记录算成多个会话。
- 先算每个用户的会话数再求平均也可以,结果一样,但要多一层子查询。