SQL Server 2005:如何排除字段存在连续重复值的行
解决连续重复状态码的保留问题
这个问题属于SQL里经典的连续相同值分组(岛屿问题),你踩的坑太常见了——普通的GROUP BY或者仅按status_code分区的ROW_NUMBER()函数,只会根据值本身分组,完全不关注行的顺序和连续的上下文,自然会把所有状态为"B"的记录归为一组,而忽略了它们是两次独立的状态变更(非"B"→"B")。
核心思路:标记连续相同状态的分组
我们需要先给每一段连续相同的状态码打上唯一的分组ID,这样哪怕状态码相同,只要中间有其他状态隔开,就会被分到不同的组里。具体步骤如下:
- 使用
LAG()窗口函数获取当前行的上一行状态码,对比当前行的状态码——如果不同,说明是新的状态组的开始,标记为1;如果相同,标记为0。 - 对这个标记值做累加(
SUM() OVER (ORDER BY record_date)),这样每一段连续相同的状态码会得到一个唯一的group_id。 - 最后按
group_id和status_code分组,取每个组里最早的日期(状态变更的起始日期)即可。
完整SQL示例
假设你的源表名为status_log,包含record_date(日期字段)和status_code(状态码字段),可以用以下查询实现需求:
WITH status_groups AS ( SELECT record_date, status_code, -- 标记状态变更的起始行,累加得到分组ID SUM( CASE WHEN status_code = LAG(status_code) OVER (ORDER BY record_date) THEN 0 ELSE 1 END ) OVER (ORDER BY record_date) AS group_id FROM status_log ) SELECT MIN(record_date) AS change_date, -- 保留状态变更的最早日期 status_code FROM status_groups GROUP BY group_id, status_code ORDER BY change_date;
代码解释
LAG(status_code) OVER (ORDER BY record_date):按日期排序后,获取当前行的上一行状态码,用来判断是否发生了状态变更。SUM(...) OVER (ORDER BY record_date):累加状态变更标记,生成的group_id会把每一段连续相同的状态码归为一组——比如第一次从非"B"变"B"的所有连续行是group_id=2,第二次变"B"的连续行是group_id=4(假设中间有其他状态)。- 最后分组取
MIN(record_date),就是每个状态组的起始日期,也就是你需要保留的状态变更行。
内容的提问来源于stack exchange,提问作者DaveInMaine
相关产品推荐
相关产品推荐

