题目重点:汇总用户某日各类型观看时长,区分累积播放点、时长增量与多标签连接。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练watch一行一个去重播放session,watched_seconds为有效时长非累计heartbeat值;video一行一视频/单genre,day按统一业务时区派生。
解题路线
- 筛选指定day,join video维表,按user_id/genre SUM seconds。秒与分钟输出转换单独明确,不能将session数当watch time。
- 如果输入heartbeat是累计播放时长,必须先按session/seq去重并转增量或取有效最终值;直接sum所有累计点严重翻倍。暂停/seek与同视频多session是否计入由口径定。
- video多genre时桥表一对多会复制watch时长。选择主genre、全归因或加权归因需定义,否则各genre之和超过全体观看时间。
- 缺video维度时inner join会漏事件;数据质量监测丢失量,是否归Unknown由合同定。示例维表完整,不把缺失当0时长掩盖。
手动走一遍
用户u看电影a两次session,秒数10和20,合30;若同session三条累计10/20/30,真实末累计30而不是60。video只有一个genre时类型汇总和可对账总时长。
SQL 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
-- Training: watch(event_id PK,user_id,video_id,watch_date,watched_seconds)
-- Valid deduped sessions, nonnegative seconds, date derived by agreed business TZ.
-- video(video_id PK,genre). One genre per video in this training model.
SELECT w.user_id, v.genre, SUM(w.watched_seconds) AS total_watch_seconds
FROM watch w JOIN video v ON v.video_id=w.video_id
WHERE w.watch_date=:day
GROUP BY w.user_id, v.genre
ORDER BY w.user_id, v.genre;
复杂度
按日期分区扫描Wday事实与video join,hash聚合状态按user×genre;事实去重/heartbeat转换增加上游成本。索引不能让读取全日全部事件自动O(1)。
易错点与追问
容易失分的边界
- 累计heartbeat直接相加造成系统性高估。
- 多标签join未说明归因,重复分配同一时长。
继续深挖
- 跨午夜session按开始日还是按实际观看片段分配?先定时区与分割政策。
- 离线事件晚到怎样修正已发布日指标?按版本重算而非重复increment。
