SQL Server中无需游标实现表格连续日期记录合并(扁平化)
在SQL Server中合并连续日期的人口普查记录
这是典型的连续日期分组问题,用窗口函数就能高效解决,不需要游标。核心思路是给连续的日期记录打上相同的分组标识,再按分组聚合出日期范围。
假设原表结构
假设你的人口普查表名为Census,字段包括:
Resident:居民姓名Status:居民状态RecordDate:记录日期
解决方案代码
WITH RankedRecords AS ( SELECT Resident, Status, RecordDate, -- 生成分组键:连续日期的记录会拥有相同的GroupKey DATEADD(DAY, -ROW_NUMBER() OVER (PARTITION BY Resident, Status ORDER BY RecordDate), RecordDate) AS GroupKey FROM Census ) SELECT Resident, Status, MIN(RecordDate) AS StartDate, MAX(RecordDate) AS EndDate FROM RankedRecords GROUP BY Resident, Status, GroupKey ORDER BY Resident, StartDate;
逻辑解释
- 生成分组键:
- 用
ROW_NUMBER()按Resident和Status分区,再按RecordDate排序,给每条记录分配一个递增的行号。 - 对
RecordDate减去行号对应的天数:连续日期的记录,这个计算结果会完全相同(比如1月1日-1天、1月2日-2天,结果都是12月31日);如果日期有间隔,计算结果会产生差异,从而形成新的分组。
- 用
- 聚合分组结果:
- 按
Resident、Status和GroupKey分组,取每组的最小日期作为起始日期,最大日期作为结束日期,就得到了合并后的连续日期范围。
- 按
示例验证
比如原表有以下数据:
| Resident | Status | RecordDate |
|---|---|---|
| John Doe | Active | 2024-01-01 |
| John Doe | Active | 2024-01-02 |
| John Doe | Active | 2024-01-03 |
| John Doe | Active | 2024-01-04 |
| John Doe | Active | 2024-01-06 |
| Mary Jane | Inactive | 2024-01-01 |
| Mary Jane | Inactive | 2024-01-02 |
运行代码后会得到:
| Resident | Status | StartDate | EndDate |
|---|---|---|---|
| John Doe | Active | 2024-01-01 | 2024-01-04 |
| John Doe | Active | 2024-01-06 | 2024-01-06 |
| Mary Jane | Inactive | 2024-01-01 | 2024-01-02 |
完美实现了间隔日期拆分、连续日期合并的需求,而且性能远优于游标方案。
内容的提问来源于stack exchange,提问作者romrom72
相关产品推荐
相关产品推荐

