如何使 ROW_NUMBER 处理重复记录?

Fas*_*ous 0 t-sql sql-server sql-server-2008

我有一个包含重复事务记录的表。这些都是不错的重复项,但需要为它们分配值以使它们对于表来说是唯一的。记录的用途是按时间顺序查看它们,我使用 ROW_NUMBER 按 ID 和 ORDER BY 时间对它们进行分区。

有时它有效。有时会失败。

例子

CASE WHEN [Record] = 'Start' 
     THEN 0 
ELSE -1 + ROW_NUMBER() OVER(PARTITION BY [ID] ORDER BY [Date] DESC
END AS [RowNo]
Run Code Online (Sandbox Code Playgroud)

预期成绩

ID,   Date,  RowNo
2002, 12:30, 1
2002, 12:29, 2
2002, 12:29, 3
2002, 12:29, 4
2002, 12:28, 5
3212, 01:10, 1
3212, 01:09, 2
3212, 01:08, 3
Run Code Online (Sandbox Code Playgroud)

实际结果

ID,   Date,  RowNo
2002, 12:30, 1
2002, 12:29, 2 <---Right
2002, 12:29, 2 <---Wrong
2002, 12:29, 3 <---Right
2002, 12:28, 4
3212, 01:10, 1
3212, 01:09, 2
3212, 01:08, 3
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来保证准确性?

spe*_*593 5

嗯。 ROW_NUMBER()确实适用于重复记录。(当存在重复项时,无法确定哪一行将获得哪个值。)

你的陈述中还存在其他一些未显示的内容。一个连接操作,一个 GROUP BY,一些额外的过滤。我们不知道那是什么,但我们知道这ROW_NUMBER()确实适用于重复项。


编辑

这很可疑:

CASE WHEN [Record] = 'Start' 
    THEN 0 
ELSE -1 + ROW_NUMBER() OVER(PARTITION BY [ID] ORDER BY [Date] DESC
END AS [RowNo]
Run Code Online (Sandbox Code Playgroud)

CASE我以前从未在表达式中见过这样的分析函数。在我看来,ROW_NUMBER()只有在ELSE. (我不确定 SQL Server 实际上是如何处理的。)

如果我想RowNo成为 0, 1, 2, ... 我只需减去 1...

ROW_NUMBER() OVER(PARTITION BY [ID] ORDER BY [Date] DESC) - 1 AS RowNo
Run Code Online (Sandbox Code Playgroud)

如果需要将条件纳入[Record] = 'Start'作为评估的一部分ROW_NUMBER,那么我会将其包含在PARTITION

  OVER(PARTITION BY [ID],CASE WHEN [Record]='Start' THEN 0 END ORDER BY ...) 
Run Code Online (Sandbox Code Playgroud)

如果我需要操作 ROW_NUMBER() 返回的值,我会找到一种方法在内联视图或 CTE 的上下文中对其进行评估,以对其进行评估并返回,然后对返回的值进行处理外部查询中的值。

重点是它ROW_NUMBER()可以很好地处理重复项。如果您得到的结果不是您所期望的,那是因为语句中还存在其他内容,例如 CASE 表达式、联接或其他内容。