漏斗题
漏斗题
类型:自编场景题(漏斗转化)| 题号:— | 链接:—
关联:SQL原理_04(漏斗章节)· SQL分析场景模板 · 好友申请 II :谁有最多的好友(同为列转行+聚合)
🎯 问题描述
表结构
1 | event_log(user_id, event_name, event_time) |
事件名:view、cart、order、pay。
需求
统计从"浏览 → 加购 → 下单 → 支付"的漏斗人数。
要求每一步必须发生在第一步之后,即按时间顺序:
1 | view_time < cart_time < order_time < pay_time |
输出:view_users、cart_users、order_users、pay_users。
说明:每个用户可能多次触发同一事件,需按最早时间归并成一行再比较顺序。
💻 解题思路
思路1:MIN(CASE WHEN) 归并 + 时间递增计数(用户解法)
核心逻辑
① 子查询 person_log:按 user_id 分组,用 MIN(CASE WHEN event_name = 'xx' THEN event_time END) 把每个事件的最早时间抽成一列(列转行 → 转回列);
② 外层按时间顺序逐级比较:走到下一步的前提是上一步时间更早,用 COUNT(CASE WHEN 条件 THEN 1 END) 数各步人数;
③ 缺 ELSE 时 CASE 返回 NULL,COUNT 只数非空,因此只统计"真的依次走到该步"的用户。
代码实现
1 | WITH person_log AS ( |
🔧 修正说明:
- 原文
u_cartTHEN缺空格,已改为u_cart THEN。- 原文第一步写
COUNT(CASE WHEN u_view THEN 1 END)—— 直接拿时间做布尔判断,遇到'0000-00-00'这类假值会误判;应显式写u_view IS NOT NULL才准确。- 时间比较也可以用
DATEDIFF(u_cart, u_view) > 0,语义等价。
📊 性能分析
- 时间复杂度:(一次分组聚合即可,无 JOIN)。
- 空间复杂度:(相对输入)。
思考
- 这是严格有序漏斗:
view < cart < order < pay全部成立才算走完。若业务允许"乱序转化"(比如直接下单没加购),条件要相应放宽。 - 若要算转化率,再除以
view_users即可:cart_users / view_users等。 - 若同一用户同事件多天发生、且要求"同一会话内",需要额外按会话/时间窗切分。
📝 总结
漏斗模板:MIN(CASE WHEN 事件 THEN 时间 END) 把各步压成一行 → 按时间先后逐级比较 → COUNT(CASE WHEN ... THEN 1 END) 数各步人数(无 ELSE 即天然只数"真走到"的)。与 SQL原理_04 漏斗一节完全同源。
🔗 题集索引:LeetCode题集索引 · 算法地图:学习-数据结构与算法MOC
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 笺札!







