PySpark如何按用户和连续相同loc分组计算每组起止日期
解决方案
这是SQL场景下非常经典的连续区间(岛屿)分组问题,你之前尝试的partition by user,loc逻辑错误点在于:会把同一个用户下所有loc相同的记录分到同一组,忽略了中间可能存在其他loc插入的断层情况,最终会把你示例中loc=1的两段记录合并为一组,所以无法得到正确结果。
通用解法(支持任意日期间隔,无日期连续要求)
通过「判断loc变化标记→标记累加生成分组ID→按分组ID聚合」三步实现,兼容性最强:
SELECT `user`, MIN(date) AS startdate, MAX(date) AS enddate, loc FROM ( -- 第二步:对loc变化标记做累加,生成连续区间的唯一分组ID SELECT *, SUM(change_flag) OVER(PARTITION BY `user` ORDER BY date) AS group_id FROM ( -- 第一步:判断当前行loc和上一行是否一致,不一致打变化标记1,一致打0 SELECT `user`, date, loc, CASE WHEN LAG(loc) OVER(PARTITION BY `user` ORDER BY date) = loc THEN 0 ELSE 1 END AS change_flag FROM your_table ) t1 ) t2 GROUP BY `user`, group_id, loc ORDER BY `user`, startdate;
用你提供的测试数据执行后,输出结果和你期望的完全一致。
简化写法(仅适用于日期完全连续无断层的场景)
如果你的数据集保证同一用户的日期是连续无缺失的,也可以用日期减去排序序号的方式生成分组ID,写法更简短:
SELECT `user`, MIN(date) AS startdate, MAX(date) AS enddate, loc FROM ( SELECT *, DATE_SUB(date, INTERVAL ROW_NUMBER() OVER(PARTITION BY `user`, loc ORDER BY date) DAY) AS group_id FROM your_table ) t GROUP BY `user`, loc, group_id ORDER BY `user`, startdate;
内容的提问来源于stack exchange,提问作者wesley
相关产品推荐
相关产品推荐

