SQL Server 2005 - 排除在 1 个字段中具有连续重复值的行

SQL Server 2005 - exclude rows with consecutive duplicate values in 1 field

我有一个来源 table,其中包含 2 个字段、一个日期和一个状态代码。我需要一个查询来删除重复的连续状态代码,只保留具有不同状态的第一个日期的行。例如:

Date       Status 
10/02/2004   A
10/12/2004   B
10/14/2004   B
11/22/2004   C
11/23/2004   C
12/03/2004   C
03/05/2006   B

所需的结果集将是:

10/02/2004   A
10/12/2004   B
11/22/2004   C
03/05/2006   B

主要问题是所有的分组函数(GROUP BY和ROW_NUMBER() OVER)似乎都不关心顺序,所以在例子中,所有的"B"状态记录将被组合在一起,这是不正确的,因为状态从非 "B" 更改为 "B" 两次不同的时间。

这个问题很容易解决,使用基于游标的循环来产生结果。只需记住变量中的当前值,并在循环时测试每条记录。效果很好,但速度慢得可怕(实际数据超过 20 分钟)。

这需要在 SQL Server 2005 及更高版本上 运行,因此一些较新的窗口功能不可用。有没有一种方法可以使用基于集合的查询来执行此操作,这可能 运行 快得多?看起来这应该是一件简单的事情,但也许不是。 SO 上的其他类似问题似乎依赖于我们没有的额外 ID 或序列字段。

常规分组在这种情况下无济于事的原因是分组标准需要引用 2 个不同记录中的字段以确定是否应发生分组中断。由于 SQL 2005 落后于较新的版本,我们没有滞后函数来查看先前记录的值。相反,我们需要进行自连接才能访问先前的记录。为此,我们需要使用 ROW_NUMBER() 在 CTE 中创建一个临时序列字段。然后在自连接中使用生成的序列来查看先前的记录。我们最终得到类似的东西:

;WITH tmp AS (
  SELECT myDate,myStatus,ROW_NUMBER() OVER (ORDER BY myDate) as seq
  FROM myTable )
SELECT tmp.* FROM tmp LEFT JOIN tmp t2 ON t2.seq = tmp.seq-1
WHERE t2.seq is null OR t2.myStatus!=tmp.myStatus

因此,即使原始数据没有序列列,我们也可以动态生成它,以便能够使用自连接找到任何给定其他记录的先前记录(如果有的话) .然后我们得到期望的结果,即仅选择状态与先前记录相比发生变化的记录。