如何统计各名称对应标识的连续出现天数?
如何统计每个名称和标识对应的连续天数?
嘿,这个统计连续相同Name+Flag组合天数的需求很常见,用SQL的窗口函数就能轻松实现,咱们先理清楚数据和目标,再看具体解法:
原始数据
Name Date Flag ------------------------------------- Alberta 01-01-2018 B Alberta 02-01-2018 B Alberta 03-01-2018 B Alberta 04-01-2018 L Alberta 05-01-2018 L Ambelos 01-01-2018 B Ambelos 02-01-2018 B Ambelos 03-01-2018 L Ambelos 04-01-2018 B
期望结果
Name Date Flag CountDays ---------------------------------------------------- Alberta 03-01-2018 B 3 Alberta 05-01-2018 L 2 Ambelos 02-01-2018 B 2 Ambelos 03-01-2018 L 1 Ambelos 04-01-2018 B 1
具体实现方案(SQL)
核心思路是先把连续相同的Name+Flag组合归为一个“组”,然后统计每个组的天数,最后取每组的最后一天作为结果展示。这里用窗口函数来标记分组是最高效的方式:
完整SQL代码
-- 第一步:给连续的Name+Flag组合打组标记 WITH grouped_data AS ( SELECT Name, Date, Flag, -- 两个行号的差值作为组ID:连续相同组合的差值会一致 ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Date) - ROW_NUMBER() OVER (PARTITION BY Name, Flag ORDER BY Date) AS group_id FROM your_table_name -- 替换成你的实际表名 ), -- 第二步:按组统计天数,取每组的最后日期 aggregated_data AS ( SELECT Name, MAX(Date) AS Date, -- 取连续周期的最后一天 Flag, COUNT(*) AS CountDays -- 统计该组的天数 FROM grouped_data GROUP BY Name, Flag, group_id ) -- 第三步:输出最终结果,按名称和日期排序 SELECT Name, Date, Flag, CountDays FROM aggregated_data ORDER BY Name, Date;
代码细节说明
- 分组标记(grouped_data):用两个
ROW_NUMBER()窗口函数的差值来识别连续组。比如Alberta的前3条B记录,按Name排序的行号是1、2、3,按Name+Flag排序的行号也是1、2、3,差值都是0,属于同一组;后面两条L的差值同样一致,是另一个组。 - 统计聚合(aggregated_data):按
Name, Flag, group_id分组,用COUNT(*)得到连续天数,MAX(Date)取到连续周期的最后一天,正好对应你期望结果里的Date字段。 - 注意:如果你的
Date字段是字符串类型,要确保它的格式能正确排序(比如示例里的DD-MM-YYYY,部分数据库可能需要先转成日期类型,比如用TO_DATE(Date, 'DD-MM-YYYY')替换代码里的Date来处理)。
内容的提问来源于stack exchange,提问作者Vanessa Zorgia




