SQL分组难题:如何提取重复ID分段的时段起始时间
解决同一ID连续动作分组取起始时间的问题
嘿,这个问题其实是SQL里经典的**间隙与岛屿(Gaps and Islands)**问题的变种,你之前用rank()或者min()直接按id分组的思路,确实会把同一个id的所有记录归为一组,没法区分被其他id打断的分段。
我给你一个能完美匹配你目标输出的解决方案,思路是通过行号的差值来识别连续的同一id分组:
首先,我们给所有记录按时间排个序,生成全局行号;再给每个id内部的记录按时间排序,生成id专属行号。当同一id的记录连续出现时,这两个行号的差值会保持不变——一旦中间插入了其他id的记录,这个差值就会变化,正好用来区分不同的分组。
具体SQL代码如下(假设你的表名叫your_table):
WITH ranked_data AS ( SELECT id, t, ROW_NUMBER() OVER (ORDER BY t) AS global_rn, ROW_NUMBER() OVER (PARTITION BY id ORDER BY t) AS id_rn FROM your_table ) SELECT id, MIN(t) AS start FROM ranked_data GROUP BY id, (global_rn - id_rn) ORDER BY MIN(t);
运行这个查询后,你就能得到和目标输出完全一致的结果:把每个连续出现的同一id记录作为一组,取每组的第一个时间作为start。
原理说明
global_rn:确保所有记录按时间顺序排列,保证分组的时间逻辑正确;id_rn:给每个id内部的记录按时间依次编号,每个id的记录从1开始递增;global_rn - id_rn:作为分组的核心标识——同一连续id组的这个差值固定不变,当其他id插入时,差值会发生变化,从而将被打断的同一id记录拆分为不同分组。
如果你的“连续”定义是基于时间间隔(比如同一id相邻记录时间差不超过N分钟就算连续),那可以调整思路用时间差判断分组,但从你给出的目标输出看,上面的方法完全适配你的需求。
内容的提问来源于stack exchange,提问作者anon221231221
相关产品推荐
相关产品推荐

